我正在尝试将url编码为基于shell脚本的字符串。 我从互联网上下载了一个脚本。 它是:
#!/bin/sh
url_encoder()
{
echo -n "$1" | awk -v ORS="" '{ gsub(/./,"&\n") ; print }' | while read l;
do
case "$l" in
[-_.~/a-zA-Z0-9] ) echo -n ${l} ;;
"" ) echo -n %20 ;;
* ) printf '%%%02X' "'$l"
esac
done
}
echo ""
}
上述代码的基本思想是 (1)将输入字符串转换为行,每行有一个字符 (2)对于每一行,url编码字符
所以如果我跑
$url_encoder "abc:"
输出将是" abc%3A",这是正确的
但如果我跑
$url_encoder "\\" # I want to encode the backslash, so I use 2 "\" here
根本没有输出。
你知道原因吗?
答案 0 :(得分:4)
无需使用读取哪个慢,变量扩展可以做一个子串,不需要特别处理空格字符,它可以作为默认处理
url_encoder() {
local i str=$1 c
for ((i=0;i<${#str};i+=1)); do
c=${str:i:1}
case "$c" in
[-_.~/a-zA-Z0-9] ) echo -n "${c}" ;;
* ) printf '%%%02X' "'$c" ;;
esac
done
}
l='\'
printf '%%%02X' "'$l"
反斜杠消失的原因是因为read
具有特殊含义,-r
选项应该用来避免。
https://www.gnu.org/software/bash/manual/html_node/Bash-Builtins.html#index-read
注意~
也应编码为http://www.rfc-editor.org/rfc/rfc1738.txt
printf参数以引号(单引号或双引号)开头,仅处理ascii字符&#34;&#39; $ c&#34; (小于128)。
url_encoder() { (
LC_ALL=C
str=$1
for ((i=0;i<${#str};i+=1)); do
c=${str:i:1}
if [[ $c = [-_./a-zA-Z0-9] ]]; then
echo -n "${c}"
elif [[ $c = [$'\1'-$'\x7f'] ]]; then
printf '%%%02X' "'$c"
else
printf '%%%s' $(echo -n "$c" | od -An -tx1)
fi
done
)}
答案 1 :(得分:1)
Nahuel Fouilleul's helpful answer解释了您的方法存在的问题(-r
命令中遗漏了read
,导致对\
字符的不必要解释。)并提供了更高效的{{} {1}}解决方案。
这里是一个更高效,符合POSIX标准的解决方案(bash
- 兼容),它使用单个sh
命令执行编码,假设输入字符串仅由字符组成ASCII / Unicode代码点范围介于32和127之间,包括:
awk