我试图写一个bash脚本测试,需要一个参数,并通过curl发送到网站。我需要url编码的值,以确保特殊字符被正确处理。最好的方法是什么?

这是我到目前为止的基本脚本:

#!/bin/bash
host=${1:?'bad host'}
value=$2
shift
shift
curl -v -d "param=${value}" http://${host}/somepath $@

当前回答

下面是一个使用Lua的单行转换,类似于blueyed的答案,除了所有的RFC 3986 Unreserved Characters都没有被编码(就像这个答案):

url=$(echo 'print((arg[1]:gsub("([^%w%-%.%_%~])",function(c)return("%%%02X"):format(c:byte())end)))' | lua - "$1")

此外,您可能需要确保字符串中的换行符从LF转换为CRLF,在这种情况下,您可以插入一个gsub("\r? "“\n”,“\r\n”)在百分比编码之前。

下面是一个变体,在application/x-www-form-urlencoded的非标准风格中,它执行换行规范化,并将空格编码为'+'而不是'%20'(可以使用类似的技术将其添加到Perl代码片段中)。

url=$(echo 'print((arg[1]:gsub("\r?\n", "\r\n"):gsub("([^%w%-%.%_%~ ]))",function(c)return("%%%02X"):format(c:byte())end):gsub(" ","+"))' | lua - "$1")

其他回答

Ruby,为了完整性

value="$(ruby -r cgi -e 'puts CGI.escape(ARGV[0])' "$2")"

以下是基于奥威尔的回答,但解决了多字节 通过设置LC_ALL=C (vte.sh的一个技巧)在评论中提到的错误。 我把它写成了函数PROMPT_COMMAND的形式,因为 我就是这么用的。

print_path_url() {
  local LC_ALL=C
  local string="$PWD"
  local strlen=${#string}
  local encoded=""
  local pos c o

  for (( pos=0 ; pos<strlen ; pos++ )); do
     c=${string:$pos:1}
     case "$c" in
        [-_.~a-zA-Z0-9/] ) o="${c}" ;;
        * )               printf -v o '%%%02x' "'$c"
     esac
     encoded+="${o}"
  done
  printf "\033]7;file://%s%s\007" "${HOSTNAME:-}" "${encoded}"
}

简单的PHP选项:

echo 'part-that-needs-encoding' | php -R 'echo urlencode($argn);'

在本例中,我需要对主机名进行URL编码。不要问为什么。作为一个极简主义者和Perl爱好者,下面是我想到的。

url_encode()
  {
  echo -n "$1" | perl -pe 's/[^a-zA-Z0-9\/_.~-]/sprintf "%%%02x", ord($&)/ge'
  }

很适合我。

Python 3基于@sandro在2010年的好答案:

echo "Test & /me" | python -c "import urllib.parse;print (urllib.parse.quote(input()))"

测试% 20% 26% 20 /我