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

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

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

当前回答

如果你想运行GET请求并使用纯curl,只需添加—得到@Jacob的解决方案。

这里有一个例子:

curl -v --get --data-urlencode "access_token=$(cat .fb_access_token)" https://graph.facebook.com/me/feed

其他回答

下面是一个使用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")

Uni2ascii非常方便:

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

在bash脚本的第二行中使用Perl的URI::Escape模块和uri_escape函数:

...

value="$(perl -MURI::Escape -e 'print uri_escape($ARGV[0]);' "$2")"
...

编辑:修复引用问题,正如Chris Johnsen在评论中建议的那样。谢谢!

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

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

测试% 20% 26% 20 /我

其中一种变体可能很丑,但很简单:

urlencode() {
    local data
    if [[ $# != 1 ]]; then
        echo "Usage: $0 string-to-urlencode"
        return 1
    fi
    data="$(curl -s -o /dev/null -w %{url_effective} --get --data-urlencode "$1" "")"
    if [[ $? != 3 ]]; then
        echo "Unexpected error" 1>&2
        return 2
    fi
    echo "${data##/?}"
    return 0
}

下面是一个单行版本的例子(由Bruno建议):

date | curl -Gso /dev/null -w %{url_effective} --data-urlencode @- "" | cut -c 3-

# If you experience the trailing %0A, use
date | curl -Gso /dev/null -w %{url_effective} --data-urlencode @- "" | sed -E 's/..(.*).../\1/'