首页 > 解决方案 > 跨行匹配模式

问题描述

假设我有一个文件,其中包含:

something  
line=1  
file=2  
other  
lines  
ignore  

something  
line=2  
file=3  
other  
lines  
ignore  

最终,我想要每个部分中的行和文件组合的唯一列表。在第一阶段,我试图将sed那些组合成一行的行输出,比如

line=1file=2  
line=2file=3

然后我可以使用sortand uniq

所以我正在尝试

sed -n -r 's/(line=)(.*?)(\r)(file=)(.*?)(\r)/\1\2\4\5/p' sample.txt

(不一定只是每个后面的数字)

但它不会跨界匹配。我试过 \n 和 \r\n 但它似乎不是换行的风格,因为:

sed -n -r 's/(line=)(.*?)(\r)/\1\2/p' sample.txt

将输出“line =”行,但我无法让它跨越新行,并收集第二行。

标签: sed

解决方案


默认情况下,sed只会对由\n字符分隔的块进行操作,因此您永远不能跨多行匹配。一些sed实现支持-z选项,它将使其对由 ASCII NUL 字符而不是换行符分隔的块进行操作(这可能适用于小文件,假设 NUL 字符不会影响您要匹配的模式)

还有一些sed命令可以用于多行处理

sed -n '/line=/{N;s/\n//p}'
  • N命令将下一行添加到当前正在处理的块(line=在这种情况下必须匹配)
  • s/\n//p然后删除换行符,以便您将输出作为单行

如果您的输入具有 dos 样式行结尾,请先将其转换为 unix 样式(请参阅为什么我的工具输出会覆盖自身以及如何修复它?)或\r同时处理

sed -n '/line=/{N;s/\r\n//p}'

请注意,这些命令已经过测试GNU sed,其他实现的语法可能会有所不同


推荐阅读