3

我想把一个字符串像

AaAa

进入

像这样的字符串

%<41>%<61>%<41>%<61>

使用我熟悉的编程语言很简单,但是使用 bash 我无法正确地做我想做的事情:

  • 将字符串拆分为 char 数组
  • 将每个字符转换为十六进制
  • 将每个十六进制值包装成%<FF>
  • 连接字符串

这是我目前的方式,让我走到了一半:

echo -n "AaAa" | od -A n -t x1
4

5 回答 5

3

如果您已经在使用od

printf "%%<%s>" $(od -A n -t x1<<<"AaAa")

对于没有od,

while read -r -N 1 c; do printf "%%<%02X>" "$( printf "%d" \'$c )"; done <<< AaAa

这种方法的缺点是它为每个字符生成一个子shell,并假定为 ASCII/UTF8。


编辑

@Shawn 指出您不需要子外壳 -

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>
于 2021-07-23T20:41:28.197 回答
2

一个简单的 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" }。)

于 2021-07-23T20:35:12.323 回答
1

你可以使用

echo -n AaAa | perl -ne 'for $c (split//) { printf("%%<%02X>", ord($c)); }'

输出

%<41>%<61>%<41>%<61>
于 2021-07-23T20:08:21.830 回答
1

也许awk

echo -n "AaAa" |
od -A n -t x1 |
awk 'BEGIN { ORS = "" } { for (i = 1; i <= NF; i+=1) print "%<"$i">"}'
于 2021-07-23T20:27:03.190 回答
1

您可以通过管道sed将每个字节包装进去%<>,然后删除空格。

echo -n "AaAa" | od -A n -t x1 | sed -E -e 's/[a-z0-9]+/%<&>/g' -e 's/ //g'
于 2021-07-23T20:10:01.430 回答