用于 url 解码的 bash 习惯用法
这是一个 bash 习惯用法,用于对 variabe 中保存的字符串进行 url 解码x
并将结果分配给 variable y
:
: "${x//+/ }"; printf -v y '%b' "${_//%/\\x}"
与接受的答案不同,它在分配期间保留尾随换行符。(尝试将 url 解码的结果分配v%0A%0A%0A
给一个变量。)
它也很快。将 url 解码的结果分配给变量比接受的答案快6700% 。
警告:bash 变量不可能包含 NUL。例如,任何试图解码%00
并将结果分配给变量的 bash 解决方案都将不起作用。
基准详情
函数.sh
#!/bin/bash
urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; }
x=%21%20
for (( i=0; i<5000; i++ )); do
y=$(urldecode "$x")
done
成语.sh
#!/bin/bash
x=%21%20
for (( i=0; i<5000; i++ )); do
: "${x//+/ }"; printf -v y '%b' "${_//%/\\x}"
done
$ hyperfine --warmup 5 ./function.sh ./idiom.sh
Benchmark #1: ./function.sh
Time (mean ± σ): 2.844 s ± 0.036 s [User: 1.728 s, System: 1.494 s]
Range (min … max): 2.801 s … 2.907 s 10 runs
Benchmark #2: ./idiom.sh
Time (mean ± σ): 42.4 ms ± 1.0 ms [User: 40.7 ms, System: 1.1 ms]
Range (min … max): 40.5 ms … 44.8 ms 64 runs
Summary
'./idiom.sh' ran
67.06 ± 1.76 times faster than './function.sh'
如果你真的想要一个功能......
如果你真的想要一个函数,比如出于可读性的原因,我建议如下:
# urldecode [-v var ] argument
#
# Urldecode the argument and print the result.
# It replaces '+' with SPACE and then percent decodes.
# The output is consistent with https://meyerweb.com/eric/tools/dencoder/
#
# Options:
# -v var assign the output to shell variable VAR rather than
# print it to standard output
#
urldecode() {
local assign_to_var=
local OPTIND opt
while getopts ':v:' opt; do
case $opt in
v)
local var=$OPTARG
assign_to_var=Y
;;
\?)
echo "$FUNCNAME: error: -$OPTARG: invalid option" >&2
exit 1
;;
:)
echo "$FUNCNAME: error: -$OPTARG: this option requires an argument" >&2
exit 1
;;
*)
echo "$FUNCNAME: error: an unexpected execution path has occurred." >&2
exit 1
;;
esac
done
shift "$((OPTIND - 1))"
if [[ $assign_to_var ]]; then
: "${1//+/ }"; printf -v "$var" %b "${_//%/\\x}"
else
: "${1//+/ }"; printf %b "${_//%/\\x}"
fi
}
将解码结果分配给 shell 变量的示例:
x='v%0A%0A%0A'
urldecode -v y "$x"
echo -n "$y" | od -An -tx1
结果:
76 0a 0a 0a
这个函数虽然没有上面的习语那么快,但由于不涉及子外壳,在做作业时仍然比接受的答案快 1300%。此外,如示例输出所示,由于不涉及命令替换,它保留了尾随换行符。