包装十六进制字符串时不一致

时间:2018-05-04 19:40:26

标签: bash awk sed hexdump xxd

使用hexdump和xxd时,我有一些不一致的地方。当我运行以下命令时:

echo -n "a42d9dfe8f93515d0d5f608a576044ce4c61e61e" \
  | sed 's/\(..\)/\1\n/g' \
  | awk '/^[a-fA-F0-9]{2}$/ { printf("%c",strtonum("0x" $0)); }' \
  | xxd

它返回以下结果:

00000000: c2a4 2dc2 9dc3 bec2 8fc2 9351 5d0d 5f60  ..-........Q]._`
00000010: c28a 5760 44c3 8e4c 61c3 a61e            ..W`D..La...

请注意“c2”字符。运行xxd -p

时也会发生这种情况

当我运行相同的命令时,除了使用hexdump -C:

echo -n "a42d9dfe8f93515d0d5f608a576044ce4c61e61e" \
  | sed 's/\(..\)/\1\n/g' \
  | awk '/^[a-fA-F0-9]{2}$/ { printf("%c",strtonum("0x" $0)); }' \
  | hexdump -C

我得到相同的结果(包括“c2”字符):

00000000  c2 a4 2d c2 9d c3 be c2  8f c2 93 51 5d 0d 5f 60  |..-........Q]._`|
00000010  c2 8a 57 60 44 c3 8e 4c  61 c3 a6 1e              |..W`D..La...|

但是,当我运行没有参数的hexdump时:

echo -n "a42d9dfe8f93515d0d5f608a576044ce4c61e61e" \
  | sed 's/\(..\)/\1\n/g' \
  | awk '/^[a-fA-F0-9]{2}$/ { printf("%c",strtonum("0x" $0)); }' \
  | hexdump

我得到以下[正确]结果:

0000000 a4c2 c22d c39d c2be c28f 5193 0d5d 605f
0000010 8ac2 6057 c344 4c8e c361 1ea6

出于这个脚本的目的,我宁愿使用xxd而不是hexdump。想法?

2 个答案:

答案 0 :(得分:1)

您观察到的问题是由于UTF-8编码和little-endiannes。

首先,请注意当您尝试在AWK中打印任何Unicode字符时,例如0xA4 (CURRENCY SIGN),它实际上会产生两个字节的输出,就像您在输出中看到的两个字节0xC2 0xA4一样:

$ echo 1 | awk 'BEGIN { printf("%c", 0xA4) }' | hexdump -C

输出:

00000000  c2 a4                                             |..|
00000002

这适用于任何大于0x7F的字符,这是由于UTF-8编码,这可能是您的语言环境中设置的编码。 (注意:一些AWK实现对上面的代码会有不同的行为。)

其次,当您使用不带参数hexdump的{​​{1}}时,它会显示由于您机器的little-endianness而导致的交换顺序中的每对字节。这是因为每对字节被视为一个16位字,而不是像-Cxxd命令那样单独处理每个字节。因此,您获得的hexdump -C输出实际上是输入的正确的逐字节表示。

第三,如果你想生成用你输入sed的十六进制字符串编码的精确字节字符串,你可以使用这个Python解决方案:

xxd

输出:

echo -n "a42d9dfe8f93515d0d5f608a576044ce4c61e61e" | sed 's/\(..\)/0x\1,/g' | python3 -c "import sys;[open('tmp','wb').write(bytearray(eval('[' + line + ']'))) for line in sys.stdin]" && cat tmp | xxd

答案 1 :(得分:1)

为什么不将xxd与-r和-p一起使用?

echo a42d9dfe8f93515d0d5f608a576044ce4c61e61e | xxd -r -p | xxd

输出

0000000: a42d 9dfe 8f93 515d 0d5f 608a 5760 44ce  .-....Q]._`.W`D.
0000010: 4c61 e61e                                La..