在两个模式之间进行搜索,并多次打印从第一个模式到第二个模式的数据,排除不匹配的块

在两个模式之间进行搜索,并多次打印从第一个模式到第二个模式的数据,排除不匹配的块

我必须以相反的顺序搜索特定的字符串并打印它。

在下面的例子中,我想从模式搜索not in order直到模式number of

例如:输入文件包含:

number of characters a[1] 
reg1 
reg2 
reg3 
info a[1] is not in order

number of characters a[3] 
reg1 
reg2 
reg3 
info a[3] is in order


number of characters a[2] 
reg1 
reg2 
reg3 
info a[2] is not in order

输出应该是:

number of characters a[1]
reg1 
reg2 
reg3 
info a[1] is not in order

number of characters a[2] 
reg1 
reg2 
reg3 
info a[2] is not in order

答案1

使用in order换行符作为段落分隔符,我们可以执行以下操作:

awk -v RS='in order\n' '/not/{print $0 "in order"}'

awk将由 (记录分隔符) 中的模式分隔的文本RS视为记录,并且每个操作都针对一条记录执行。因此,/not/测试记录是否匹配not,然后我们将记录($0)与 awk 删除的分隔符文本一起打印。

所以:

$ mawk -v RS='in order\n' '/not/{print $0 "in order"}' foo
number of characters a[1]
reg1
reg2
reg3
info a[1] is not in order


number of characters a[2]
reg1
reg2
reg3
info a[2] is not in order

答案2

如果块必须以包含is in order或 的行结束is not in order,我们可以删除它们之间的内容......

$ sed '/is not in order/,/is in order/ {/is not in order/n;d}' file
number of characters a[1] 
reg1 
reg2 
reg3 
info a[1] is not in order


number of characters a[2] 
reg1 
reg2 
reg3 
info a[2] is not in order

笔记:

  • /is not in order/,/is in order/is not in order找出和之间的界线is in order(含)
  • {some commands}将这些命令分组
  • /is not in order/n从下一个命令开始跳过具有此模式的行
  • d删除指定行

找到这一行然后再次找到它来跳过它似乎很复杂,但我们不能用空行来代替,否则sed会打开它的在这里操作在下一个空行处标记并继续直到下一个is in order,这将删除过多。

答案3

另一种方法:

tac file | awk ' BEGIN {weprint=0 ; rem="not necessary, but for clarity"}
  /is not in order$/ { weprint=1 ;}
  ( weprint == 1)    { print $0  ;   rem="same remark here..."; }
  /^number of/       { weprint=0 ;}
' | tac

如果需要的话可以缩短...

如果您想要分隔线:将最后一行更改为

"/^number of/" { print ; weprint=0;}

答案4

perl -00 -ne 'print if /not in order/' file

-00选项按段落读取文件。在文件的所有段落上添加一个隐式循环。
然后 ,如果段落包含所需的“无序”文本,则打印该段落。-n

相关内容