sed -n '/pattern1/,/pattern2/p'
pattern1
a
b
pattern2
cd
pattern1
ef
pattern2
gh
pattern1
ef
pattern2
这将在所有匹配的pattern1和pattern2之间生成输出
但是我如何选择打印哪个块只打印最后一个匹配的模式块或仅打印第一个匹配的模式块?
答案 0 :(得分:2)
以下是使用awk的一种方法:
$ awk '/pattern1/{++f;p=1}p&&f==2;/pattern2/{p=0}' file
pattern1
ef
pattern2
中间的数字2
控制打印的事件(在本例中为第二个)。
当打开模式匹配时,f
递增,并设置p
标志。匹配结束模式时,p
标志未设置。只有在p
标志设置且f
具有特定值时才会打印行。
如果您愿意,可以从shell传递值:
$ c=2
$ awk -v c="$c" '/pattern1/{++f;p=1}p&&f==c;/pattern2/{p=0}' file
pattern1
ef
pattern2
要始终打印范围内的最后一个匹配项,可以使用数组:
$ awk '{a[NR]=$0}/pattern1/{s=NR}/pattern2/{e=NR}END{for(i=s;i<=e;++i)print a[i]}' file
pattern1
ef
pattern2
文件中的每一行都按顺序存储在数组a
中。每次匹配开始或结束模式时,s
和e
都会被当前行号NR覆盖。最后,打印您感兴趣的元素。
这种方法的一个潜在缺点是整个文件的内容都存储在内存中,但除非你有非常大的文件,否则这可能不是问题。
答案 1 :(得分:1)
另一种方式
awk -vM=2 '(x+=/pattern1/)==M&&x+=/pattern2/' file
pattern1
ef
pattern2
-vM=2
将M设置为您想要查找的任何内容
(x+=/pattern1/)==M
x
每次出现时增加pattern1
,并检查它是否等于M
。
&&x+=/pattern2/
如果确实如此,那么每次出现pattern2
时都会增加它,所以当它到达模式2时,它会打印出那条线,但不会更多,因为它现在会大于M。
awk的默认操作是打印。
这只存储在内存中看到的最后一个块。
awk 'x+=/pattern1|pattern2/{!y++&&B="";B=B?B"\n"$0:$0;x==2&&y=x=0}END{print B}' file
pattern1
ef
pattern2
每次出现pattern1或2时增加x
当没有设置y时(当找到新的集合时)刷新B然后设置y
如果x存在则将线添加到变量B
如果计数为2则取消设置x和y意味着两者都已被看到。
答案 2 :(得分:0)
Perl救援!
perl -ne 'push @keep, $_ if (/pattern1/ and @keep = ("")) .. /pattern2/;
}{ print @keep'
说明:匹配存储在@keep中,当pattern1
匹配时,该匹配将被清空。因此,@ keep将在处理完整个输入后包含最后一个匹配。
perl -ne 'push @keep, $_
if (/pattern1/ and ++$c and @keep = "")
.. ($e = /pattern2/);
print(@keep), last if $e and 2 == $c'
# ^
# |
# the second match
$ c计算比赛次数。 $ e表示比赛结束。