问题描述
如何在命令行上编码和解码percent-encoded(URL编码)字符串?
我正在寻找可以做到这一点的解决方案:
$ percent-encode "ændrük"
%C3%A6ndr%C3%BCk
$ percent-decode "%C3%A6ndr%C3%BCk"
ændrük
最佳解决思路
这些命令可以满足您的需求:
python -c "import urllib, sys; print urllib.quote(sys.argv[1])" æ
python -c "import urllib, sys; print urllib.unquote(sys.argv[1])" %C3%A6
如果要将空格编码为+
,请将urllib.quote
替换为urllib.quote_plus
。
我猜你会想要如何创建一个永久“alias”? 😉
次佳解决思路
shell
请尝试以下命令行:
$ echo "%C3%A6ndr%C3%BCk" | sed 's@+@ @g;s@%@\\x@g' | xargs -0 printf "%b"
ændrük
您可以将其定义为别名并将其添加到shell rc文件中:
$ alias urldecode='sed "s@+@ @g;s@%@\\\\x@g" | xargs -0 printf "%b"'
然后,每当您需要它时,只需使用:
$ echo "http%3A%2F%2Fwww" | urldecode
http://www
bash
编写脚本时,您可以使用以下语法:
input="http%3A%2F%2Fwww"
decoded=$(printf '%b' "${input//%/\\x}")
但是上面的语法不能正确处理加号(+
),因此您需要通过sed
用空格替换它们。
您还可以使用以下urlencode()
和urldecode()
功能:
urlencode() {
# urlencode <string>
local length="${#1}"
for (( i = 0; i < length; i++ )); do
local c="${1:i:1}"
case $c in
[a-zA-Z0-9.~_-]) printf "$c" ;;
*) printf '%%%02X' "'$c"
esac
done
}
urldecode() {
# urldecode <string>
local url_encoded="${1//+/ }"
printf '%b' "${url_encoded//%/\\x}"
}
Note that your urldecode() assumes the data contains no backslash.
bash + xxd
使用xxd
工具进行Bash功能:
urlencode() {
local length="${#1}"
for (( i = 0; i < length; i++ )); do
local c="${1:i:1}"
case $c in
[a-zA-Z0-9.~_-]) printf "$c" ;;
*) printf "$c" | xxd -p -c1 | while read x;do printf "%%%s" "$x";done
esac
done
}
发现于cdown’s gist file,也位于stackoverflow。
Python
尝试定义以下别名:
alias urldecode='python -c "import sys, urllib as ul; print ul.unquote_plus(sys.argv[1])"'
alias urlencode='python -c "import sys, urllib as ul; print ul.quote_plus(sys.argv[1])"'
用法:
$ urlencode "ændrük"
C%26ndrC%3Ck
$ urldecode "%C3%A6ndr%C3%BCk"
ændrük
资料来源:ruslanspivak
PHP
使用PHP,您可以尝试以下命令:
$ echo oil+and+gas | php -r 'echo urldecode(fgets(STDIN));' // Or: php://stdin
oil and gas
要不就:
php -r 'echo urldecode("oil+and+gas");'
使用-R
进行多行输入。
Perl
在Perl中,您可以使用URI::Escape
。
decoded_url=$(perl -MURI::Escape -e 'print uri_unescape($ARGV[0])' "$encoded_url")
或者处理文件:
perl -i -MURI::Escape -e 'print uri_unescape($ARGV[0])' file
sed
使用sed
可以通过以下方式实现:
cat file | sed -e's/%\([0-9A-F][0-9A-F]\)/\\\\\x\1/g' | xargs echo -e
awk
试试anon解决方案:
awk -niord '{printf RT?$0chr("0x"substr(RT,2)):$0}' RS=%..
请参阅:Using awk printf to urldecode text。
解码文件名
如果需要从文件名中删除url编码,请使用renameutils
中的deurlname
工具(例如deurlname *.*
)。
也可以看看:
有关:
第三种解决思路
Percent-encode保留URI字符和non-ASCII字符
jq -s -R -r @uri
-s
(--slurp
)将输入行读入数组,-s -R
(--slurp --raw-input
)将输入读入单个字符串。 -r
(--raw-output
)输出字符串的内容而不是JSON字符串文字。
Percent-encode所有人物
xxd -p|tr -d \\n|sed 's/../%&/g'
tr -d \\n
删除每60个字符后由xxd -p
添加的换行符。
Percent-encode除Bash中的ASCII字母数字字符外的所有字符
eu () {
local LC_ALL=C c
while IFS= read -r -n1 -d '' c
do
if [[ $c = [[:alnum:]] ]]
then
printf %s "$c"
else
printf %%%02x "'$c"
fi
done
}
如果没有-d ''
,这将跳过换行符和空字节。如果没有IFS=
,这将用%00
替换IFS
中的字符。没有LC_ALL=C
,这将例如用UTF-8场所中的%3042
替换あ
。
第四种思路
仅用于解码的纯bash解决方案:
$ a='%C3%A6ndr%C3%BCk'
$ echo -e "${a//%/\\x}"
ændrük
第五种思路
我无法评论best answer in this thread,所以这是我的。
就个人而言,我使用这些别名进行URL编码和解码:
alias urlencode='python -c "import urllib, sys; print urllib.quote( sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1])"'
alias urldecode='python -c "import urllib, sys; print urllib.unquote(sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1])"'
这两个命令都允许您转换数据,作为命令行参数传递或从标准输入读取,因为one-liners检查是否存在命令行参数(甚至是空参数)并处理它们或者只读取标准输入。
更新2015-07-16(空第1个arg)
……根据@muru评论。
更新2017-05-28(斜杠编码)
如果你还需要对斜杠进行编码,只需在quote函数中添加一个空的第二个参数,然后斜杠也将被编码。
所以,最后Bash中的urlencode
别名如下所示:
alias urlencode='python -c "import urllib, sys; print urllib.quote(sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1], \"\")"'
例子
$ urlencode "Проба пера/Pen test"
%D0%9F%D1%80%D0%BE%D0%B1%D0%B0%20%D0%BF%D0%B5%D1%80%D0%B0%2FPen%20test
$ echo "Проба пера/Pen test" | urlencode
%D0%9F%D1%80%D0%BE%D0%B1%D0%B0%20%D0%BF%D0%B5%D1%80%D0%B0%2FPen%20test
$ urldecode %D0%9F%D1%80%D0%BE%D0%B1%D0%B0%20%D0%BF%D0%B5%D1%80%D0%B0%2FPen%20test
Проба пера/Pen test
$ echo "%D0%9F%D1%80%D0%BE%D0%B1%D0%B0%20%D0%BF%D0%B5%D1%80%D0%B0%2FPen%20test" | urldecode
Проба пера/Pen test
$ urlencode "Проба пера/Pen test" | urldecode
Проба пера/Pen test
$ echo "Проба пера/Pen test" | urlencode | urldecode
Проба пера/Pen test
第六种思路
我找到了一个包renameutils
,它包含实用程序deurlname
,它能够重命名包含”percent-encoded”字符的文件。
不幸的是,它不解码stdin或命令行选项,而只重命名文件,因此你必须创建一个虚拟文件来获取解码(重命名文件的名称),但是使用一些bash脚本可以自动化该过程。
没有关于编码部分的信息,即使因为编码哪些字符可能有问题。只有non-ASCII?
我认为应该有一些更好的工具/方法。
参考资料