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

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

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

当前回答

Ruby,为了完整性

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

其他回答

Uni2ascii非常方便:

$ echo -ne '你好世界' | uni2ascii -aJ
%E4%BD%A0%E5%A5%BD%E4%B8%96%E7%95%8C

下面是一个POSIX函数:

url_encode() {
   awk 'BEGIN {
      for (n = 0; n < 125; n++) {
         m[sprintf("%c", n)] = n
      }
      n = 1
      while (1) {
         s = substr(ARGV[1], n, 1)
         if (s == "") {
            break
         }
         t = s ~ /[[:alnum:]_.!~*\47()-]/ ? t s : t sprintf("%%%02X", m[s])
         n++
      }
      print t
   }' "$1"
}

例子:

value=$(url_encode "$2")

为了完整起见,许多使用sed或awk的解决方案只翻译一组特殊的字符,因此代码大小相当大,也不翻译其他应该编码的特殊字符。

urlencode的一个安全方法是对每个字节进行编码——即使是那些允许的字节。

echo -ne 'some random\nbytes' | xxd -plain | tr -d '\n' | sed 's/\(..\)/%\1/g'

XXD在这里小心地将输入处理为字节而不是字符。

编辑:

xxd附带了Debian中的vim-common包,我只是在一个没有安装它的系统上,我不想安装它。另一种选择是使用Debian中的bsdmainutils包中的hexdump。根据下图,bsdmainutils和vim-common应该有相同的可能性被安装:

http://qa.debian.org/popcon-png.php?packages=vim-common%2Cbsdmainutils&show_installed=1&want_legend=1&want_ticks=1

但是这里有一个使用hexdump代替XXD的版本,并且允许避免tr调用:

echo -ne 'some random\nbytes' | hexdump -v -e '/1 "%02x"' | sed 's/\(..\)/%\1/g'

Ruby,为了完整性

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

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

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

测试% 20% 26% 20 /我