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

标签 regex sed character-encoding binaryfiles

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

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\)/\1/p' test.bin | hexdump -C
# 00000000  00 0f 32 7a b0 00 00 01  0a                       |..2z.....|
# 00000009

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

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

这可行 - 现在让我们做同样的事情,但也对尾部部分:

sed -n 's/.*\(\x0f\x32\x7a\).*/\1/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 永远不会找到它们,因此它根本不会解释该字符。

如果您想“修复”它,请告诉 sed 使用“好旧的”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\).*/\1/p' |
  hexdump -C

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

关于regex - 仅使用 sed 打印二进制匹配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28165705/

相关文章:

python - 除非字符串在python中用引号引起来,否则如何将字符串拆分为字符串?

linux - 在 shell 脚本中从文件中提取特定模式

linux - 如何在特定条件下更改特定字段的值

php - 为什么 html_entity_decode() 适用于第一个字符串,而不适用于第二个?

html - 仅将非 ASCII 字符编码为 HTML 实体,保留 HTML 标记

python - Python 正则表达式中允许的最大重复次数是多少?

regex - htaccess - 删除带有编码重音字符的域后的多个斜杠

使用 awk 使用 sha1sum 进行散列

c++ - 如何在 gtk 中设置包含宽字符的文本?

php - 如何使用正则表达式将字符串拆分为二维数组?