bash 如何为 curl 命令对数据进行 urlencode?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/296536/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to urlencode data for curl command?
提问by Aaron
I am trying to write a bash script for testing that takes a parameter and sends it through curl to web site. I need to url encode the value to make sure that special characters are processed properly. What is the best way to do this?
我正在尝试编写一个用于测试的 bash 脚本,该脚本接受一个参数并通过 curl 将其发送到网站。我需要对值进行 url 编码以确保特殊字符得到正确处理。做这个的最好方式是什么?
Here is my basic script so far:
到目前为止,这是我的基本脚本:
#!/bin/bash
host=${1:?'bad host'}
value=
shift
shift
curl -v -d "param=${value}" http://${host}/somepath $@
回答by Jacob Rask
Use curl --data-urlencode
; from man curl
:
使用curl --data-urlencode
; 来自man curl
:
This posts data, similar to the other
--data
options with the exception that this performs URL-encoding. To be CGI-compliant, the<data>
part should begin with a name followed by a separator and a content specification.
这发布数据,类似于其他
--data
选项,除了它执行 URL 编码。要符合 CGI,该<data>
部分应以名称开头,后跟分隔符和内容规范。
Example usage:
用法示例:
curl \
--data-urlencode "paramName=value" \
--data-urlencode "secondParam=value" \
http://example.com
See the man pagefor more info.
有关更多信息,请参阅手册页。
This requires curl 7.18.0 or newer (released January 2008). Use curl -V
to check which version you have.
这需要curl 7.18.0 或更新版本(2008 年 1 月发布)。使用 curl -V
来检查你所拥有的版本。
回答by Orwellophile
Here is the pure BASH answer.
这是纯粹的 BASH 答案。
rawurlencode() {
local string=""
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
echo "${encoded}" # You can either set a return variable (FASTER)
REPLY="${encoded}" #+or echo the result (EASIER)... or both... :p
}
You can use it in two ways:
您可以通过两种方式使用它:
easier: echo http://url/q?=$( rawurlencode "$args" )
faster: rawurlencode "$args"; echo http://url/q?${REPLY}
[edited]
[编辑]
Here's the matching rawurldecode() function, which - with all modesty - is awesome.
这是匹配的 rawurldecode() 函数,它 - 谦虚 - 很棒。
# Returns a string in which the sequences with percent (%) signs followed by
# two hex digits have been replaced with literal characters.
rawurldecode() {
# This is perhaps a risky gambit, but since all escape characters must be
# encoded, we can replace %NN with \xNN and pass the lot to printf -b, which
# will decode hex for us
printf -v REPLY '%b' "${1//%/\x}" # You can either set a return variable (FASTER)
echo "${REPLY}" #+or echo the result (EASIER)... or both... :p
}
With the matching set, we can now perform some simple tests:
有了匹配集,我们现在可以执行一些简单的测试:
$ diff rawurlencode.inc.sh \
<( rawurldecode "$( rawurlencode "$( cat rawurlencode.inc.sh )" )" ) \
&& echo Matched
Output: Matched
And if you really really feel that you need an external tool (well, it will go a lot faster, and might do binary files and such...) I found this on my OpenWRT router...
如果你真的觉得你需要一个外部工具(好吧,它会运行得更快,并且可能会处理二进制文件之类的......)我在我的 OpenWRT 路由器上找到了这个......
replace_value=$(echo $replace_value | sed -f /usr/lib/ddns/url_escape.sed)
Where url_escape.sed was a file that contained these rules:
其中 url_escape.sed 是一个包含以下规则的文件:
# sed url escaping
s:%:%25:g
s: :%20:g
s:<:%3C:g
s:>:%3E:g
s:#:%23:g
s:{:%7B:g
s:}:%7D:g
s:|:%7C:g
s:\:%5C:g
s:\^:%5E:g
s:~:%7E:g
s:\[:%5B:g
s:\]:%5D:g
s:`:%60:g
s:;:%3B:g
s:/:%2F:g
s:?:%3F:g
s^:^%3A^g
s:@:%40:g
s:=:%3D:g
s:&:%26:g
s:$:%24:g
s:\!:%21:g
s:\*:%2A:g
回答by dubek
Use Perl's URI::Escape
module and uri_escape
function in the second line of your bash script:
在 bash 脚本的第二行中使用 Perl 的URI::Escape
模块和uri_escape
函数:
...
value="$(perl -MURI::Escape -e 'print uri_escape($ARGV[0]);' "")"
...
Edit:Fix quoting problems, as suggested by Chris Johnsen in the comments. Thanks!
编辑:修复引用问题,正如 Chris Johnsen 在评论中所建议的那样。谢谢!
回答by josch
for the sake of completeness, many solutions using sed
or awk
only translate a special set of characters and are hence quite large by code size and also dont translate other special characters that should be encoded.
为了完整起见,许多解决方案使用sed
或awk
仅翻译一组特殊字符,因此代码大小非常大,也不翻译其他应编码的特殊字符。
a safe way to urlencode would be to just encode every single byte - even those that would've been allowed.
一种安全的 urlencode 方法是只对每个字节进行编码——即使是那些被允许的字节。
echo -ne 'some random\nbytes' | xxd -plain | tr -d '\n' | sed 's/\(..\)/%/g'
xxd is taking care here that the input is handled as bytes and not characters.
xxd 在这里注意输入被处理为字节而不是字符。
edit:
编辑:
xxd comes with the vim-common package in Debian and I was just on a system where it was not installed and I didnt want to install it. The altornative is to use hexdump
from the bsdmainutils package in Debian. According to the following graph, bsdmainutils and vim-common should have an about equal likelihood to be installed:
xxd 带有 Debian 中的 vim-common 包,我只是在一个没有安装它的系统上,我不想安装它。替代方案是hexdump
从 Debian 中的 bsdmainutils包中使用。根据下图,bsdmainutils 和 vim-common 应该具有大致相等的安装可能性:
but nevertheless here a version which uses hexdump
instead of xxd
and allows to avoid the tr
call:
但尽管如此,这里有一个使用hexdump
代替xxd
并允许避免tr
调用的版本:
echo -ne 'some random\nbytes' | hexdump -v -e '/1 "%02x"' | sed 's/\(..\)/%/g'
回答by nisetama
Another option is to use jq
(as a filter):
另一种选择是使用jq
(作为过滤器):
jq -sRr @uri
-R
(--raw-input
) treats input lines as strings instead of parsing them as JSON and -sR
(--slurp --raw-input
) reads the input into a single string. -r
(--raw-output
) outputs the contents of strings instead of JSON string literals.
-R
( --raw-input
) 将输入行视为字符串而不是将它们解析为 JSON 并且-sR
( --slurp --raw-input
) 将输入读入单个字符串。-r
( --raw-output
) 输出字符串的内容而不是 JSON 字符串文字。
If the input is not the output of another command, you can store it in a jq
string variable:
如果输入不是另一个命令的输出,您可以将其存储在jq
字符串变量中:
jq -nr --arg v "my shell string" '$v|@uri'
-n
(--null-input
) does not read input, and --arg name value
stores value
in variable name
as a string. In the filter, $name
(in single quotes, to avoid expansion by the shell), references the variable name
.
-n
( --null-input
) 不读取输入,并作为字符串--arg name value
存储value
在变量name
中。在过滤器中$name
(在单引号中,以避免被 shell 扩展),引用变量name
。
Wrapped as a Bash function, this becomes:
包装为 Bash 函数,这将变为:
function uriencode { jq -nr --arg v "" '$v|@uri'; }
Or this percent-encodes all bytes:
或者这个百分比编码所有字节:
xxd -p|tr -d \n|sed 's/../%&/g'
回答by Sergey
One of variants, may be ugly, but simple:
变体之一,可能很丑,但很简单:
urlencode() {
local data
if [[ $# != 1 ]]; then
echo "Usage: 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/..(.*)...//'
string-to-urlencode"
return 1
fi
data="$(curl -s -o /dev/null -w %{url_effective} --get --data-urlencode "" "")"
if [[ $? != 3 ]]; then
echo "Unexpected error" 1>&2
return 2
fi
echo "${data##/?}"
return 0
}
Here is the one-liner version for example (as suggested by Bruno):
例如,这是单行版本(如Bruno所建议的):
encoded_value=$(python -c "import urllib; print urllib.quote('''$value''')")
回答by sandro
I find it more readable in python:
我发现它在 python 中更具可读性:
"http://www.rai.it/dl/audio/" "1264165523944Ho servito il re d'Inghilterra - Puntata 7
the triple ' ensures that single quotes in value won't hurt. urllib is in the standard library. It work for exampple for this crazy (real world) url:
三重 ' 确保 value 中的单引号不会受到伤害。urllib 在标准库中。例如,它适用于这个疯狂的(现实世界)网址:
perl -p -e 's/([^A-Za-z0-9])/sprintf("%%%02X", ord())/seg'
回答by blueyed
回答by Piotr Czapla
If you wish to run GET
request and use pure curl just add --get
to @Jacob's solution.
如果您希望运行GET
请求并使用纯 curl,只需添加--get
到@Jacob 的解决方案中即可。
Here is an example:
下面是一个例子:
after=$(echo -e "$before" | od -An -tx1 | tr ' ' % | xargs printf "%s")
回答by chenzhiwei
This may be the best one:
这可能是最好的一个:
##代码##