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

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

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

当前回答

我发现在python中可读性更好:

encoded_value=$(python3 -c "import urllib.parse; print urllib.parse.quote('''$value''')")

三重'确保单引号的值不会有伤害。Urllib在标准库中。它的工作,例如这个疯狂的(现实世界)url:

"http://www.rai.it/dl/audio/" "1264165523944Ho servito il re d'Inghilterra - Puntata 7

其他回答

下面是一个不调用任何外部程序的Bash解决方案:

uriencode() {
  s="${1//'%'/%25}"
  s="${s//' '/%20}"
  s="${s//'"'/%22}"
  s="${s//'#'/%23}"
  s="${s//'$'/%24}"
  s="${s//'&'/%26}"
  s="${s//'+'/%2B}"
  s="${s//','/%2C}"
  s="${s//'/'/%2F}"
  s="${s//':'/%3A}"
  s="${s//';'/%3B}"
  s="${s//'='/%3D}"
  s="${s//'?'/%3F}"
  s="${s//'@'/%40}"
  s="${s//'['/%5B}"
  s="${s//']'/%5D}"
  printf %s "$s"
}

使用curl——data-urlencode;来自man curl:

它发布数据,类似于其他——data选项,不同的是它执行url编码。为了与cgi兼容,<data>部分应该以名称开头,后面跟着分隔符和内容规范。

使用示例:

curl \
    --data-urlencode "paramName=value" \
    --data-urlencode "secondParam=value" \
    http://example.com

有关更多信息,请参阅手册页。

这需要curl 7.18.0或更新版本(发布于2008年1月)。使用curl -V来检查您拥有的版本。

你也可以对查询字符串进行编码:

curl --get \
    --data-urlencode "p1=value 1" \
    --data-urlencode "p2=value 2" \
    http://example.com
    # http://example.com?p1=value%201&p2=value%202
url=$(echo "$1" | sed -e 's/%/%25/g' -e 's/ /%20/g' -e 's/!/%21/g' -e 's/"/%22/g' -e 's/#/%23/g' -e 's/\$/%24/g' -e 's/\&/%26/g' -e 's/'\''/%27/g' -e 's/(/%28/g' -e 's/)/%29/g' -e 's/\*/%2a/g' -e 's/+/%2b/g' -e 's/,/%2c/g' -e 's/-/%2d/g' -e 's/\./%2e/g' -e 's/\//%2f/g' -e 's/:/%3a/g' -e 's/;/%3b/g' -e 's//%3e/g' -e 's/?/%3f/g' -e 's/@/%40/g' -e 's/\[/%5b/g' -e 's/\\/%5c/g' -e 's/\]/%5d/g' -e 's/\^/%5e/g' -e 's/_/%5f/g' -e 's/`/%60/g' -e 's/{/%7b/g' -e 's/|/%7c/g' -e 's/}/%7d/g' -e 's/~/%7e/g')

这将对$1中的字符串进行编码,并将其输出到$url中。尽管你不需要把它放在var中。顺便说一句,没有包括sed for选项卡,认为它会把它变成空格

这是节点版本:

uriencode() {
  node -p "encodeURIComponent('${1//\'/\\\'}')"
}

另一种php方法:

echo "encode me" | php -r "echo urlencode(file_get_contents('php://stdin'));"