我想把一个字符串变成
AaAa
到
像这样的字符串
%<41>%<61>%<41>%<61>
对于我熟悉的编程语言来说足够简单,但是对于bash,我不能得到正确的管道来做我想做的事情:
- 将字符串拆分为char数组
- 将每个字符转换为十六进制
- 将每个十六进制值包装到
%<FF>
- concat字符串
这是我目前的路线,我只走了一半的路程:
echo -n "AaAa" | od -A n -t x1
如果您已经在使用od
,
printf "%%<%s>" $(od -A n -t x1<<<"AaAa")
对于没有od
的all-bash,
while read -r -N 1 c; do printf "%%<%02X>" "$( printf "%d" '$c )"; done <<< AaAa
这种方法的缺点是它为每个字符生成一个子shell,并假设是ASCII/UTF8。
编辑@Shawn指出你不需要子shell -
while read -r -N 1 c; do printf "%%<%02X>" '$c; done <<< AaAa
我注意到这些在您的输出中留下了字符串终止符,并且意识到我可以通过将数据分配给变量并使用内置解析工具来消除它和read
。
$: x=AaAa && for((i=0;i<${#x};i++)); do printf "%%<%02X>" '${x:i:1}; done; echo
%<41>%<61>%<41>%<61>
一个简单的Perl替换就可以做到:
echo -n AaAa | perl -pe's/(.)/ sprintf "%%<%02X>", ord($1) /seg'
短:
echo -n AaAa | perl -ne'printf "%%<%02X>", $_ for unpack "C*"'
在两种情况下,输出都是预期的
%<41>%<61>%<41>%<61>
(没有添加尾随换行。如果您需要一个,请附加; END { print "n" }
。)
您可以管道到sed
,在%<>
中包装每个字节,然后删除空白。
echo -n "AaAa" | od -A n -t x1 | sed -E -e 's/[a-z0-9]+/%<&>/g' -e 's/ //g'
您可以使用perl:
echo -n AaAa | perl -ne 'for $c (split//) { printf("%%<%02X>", ord($c)); }'
输出%<41>%<61>%<41>%<61>
可能是awk
echo -n "AaAa" |
od -A n -t x1 |
awk 'BEGIN { ORS = "" } { for (i = 1; i <= NF; i+=1) print "%<"$i">"}'