我试图写一个bash脚本测试,需要一个参数,并通过curl发送到网站。我需要url编码的值,以确保特殊字符被正确处理。最好的方法是什么?
这是我到目前为止的基本脚本:
#!/bin/bash
host=${1:?'bad host'}
value=$2
shift
shift
curl -v -d "param=${value}" http://${host}/somepath $@
我试图写一个bash脚本测试,需要一个参数,并通过curl发送到网站。我需要url编码的值,以确保特殊字符被正确处理。最好的方法是什么?
这是我到目前为止的基本脚本:
#!/bin/bash
host=${1:?'bad host'}
value=$2
shift
shift
curl -v -d "param=${value}" http://${host}/somepath $@
当前回答
这个基于nodejs的答案将在stdin上使用encodeURIComponent:
uriencode_stdin() {
node -p 'encodeURIComponent(require("fs").readFileSync(0))'
}
echo -n $'hello\nwörld' | uriencode_stdin
hello%0Aw%C3%B6rld
其他回答
其中一种变体可能很丑,但很简单:
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/'
为了完整起见,许多使用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'
问题是关于在bash中这样做,不需要python或perl,因为实际上有一个命令,它完全是你想要的-“urlencode”。
value=$(urlencode "${2}")
这也更好,因为上面的perl答案,例如,没有正确编码所有字符。尝试使用从Word中获得的长破折号,你会得到错误的编码。
注意,你需要安装"gridsite-clients"来提供这个命令:
sudo apt install gridsite-clients
这可能是最好的一个:
after=$(echo -e "$before" | od -An -tx1 | tr ' ' % | xargs printf "%s")
对于我的一个案例,我发现NodeJS url库有最简单的解决方案。当然是YMMV
$ urlencode(){ node -e "console.log(require('url').parse(process.argv.slice(1).join('+')).href)" "$@"; }
$ urlencode "https://example.com?my_database_has=these 'nasty' query strings in it"
https://example.com/?my_database_has=these%20%27nasty%27%20query%20strings%20in%20it