仅使用 sed 打印二进制匹配项?

Print binary matches only with sed?

让我们先来一个二进制测试文件:

echo -e '\x00\x01\x00\x0a\x00\x0f\x32\x7a\xb0\x00\x00\x01' > test.bin

hexdump -C test.bin 
# 00000000  00 01 00 0a 00 0f 32 7a  b0 00 00 01 0a           |......2z.....|
# 0000000d

现在让我们看看我是否可以将字节序列 0x0f 0x32 0x7a 与 sed:

匹配
sed -n 's/\(\x0f\x32\x7a\)//p' test.bin | hexdump -C
# 00000000  00 0f 32 7a b0 00 00 01  0a                       |..2z.....|
# 00000009

按预期工作 - 打印的匹配项是从最后一个换行符 0x0a 到 下一个 结尾。现在,我只想打印匹配 - 首先我尝试在开始时用 .* 正则表达式过滤掉:

sed -n 's/.*\(\x0f\x32\x7a\)//p' test.bin | hexdump -C
# 00000000  0f 32 7a b0 00 00 01 0a                           |.2z.....|
# 00000008

行得通 - 现在让我们做同样的事情,但也适用于尾随部分:

sed -n 's/.*\(\x0f\x32\x7a\).*//p' test.bin | hexdump -C
# 00000000  0f 32 7a b0 00 00 01 0a                           |.2z.....|
# 00000008

好吧,那 工作 - 只删除了标题部分 - 但尾随部分继续,即使我也终止了我的 sed 匹配模式.* ??!

这是怎么回事 - 我怎样才能让 sed 在输出中仅打印出字节 0x0f 0x32 0x7a(考虑到 hexdump sed 将在打印匹配项时添加最后的换行符 0x0a)?

有意思。这是一个更简单的重现案例:

echo -en '\xff\x80' | sed -n 's/\xff.*/!/p' | hexdump -C

上面的打印 21 80!\x80\x80 也可以是更大的 ASCII 码,但不能更小:\x7Fsed 做预期的事情,只打印 !.

另请查看它的作用:

echo -en '\xff\x80' | sed -n 's/\xff./!/p' | hexdump -C

它什么都不打印。

那么问题就变成了,\x80 及更高版本有什么特别之处?好吧,当然 UTF-8!在 UTF-8 中,设置代码点的第一位表示更多字节即将到来。 sed 永远找不到它们,所以它根本不会解释这个字符。

如果你想 "fix" 它,告诉 sed 使用 "good old" C 语言环境:

LC_ALL=C sed ...

然后你得到预期的输出:

echo -e '\x00\x01\x00\x0a\x00\x0f\x32\x7a\xb0\x00\x00\x01' |
  LC_ALL=C sed -n 's/.*\(\x0f\x32\x7a\).*//p' |
  hexdump -C

00000000  0f 32 7a 0a                                       |.2z.|