测试文件如下:
PATTERN1
a
b
c
PATTERN2
d
e
f
PATTERN2
g
h
我想打印PATTERN1
第二个匹配之间的行PATTERN2
:
PATTERN1
a
b
c
PATTERN2
d
e
f
PATTERN2
答案1
这是一种方法sed
:
sed '/PATTERN1/,$!d;/PATTERN2/{x;//{x;q;};g;}' infile
这只是删除第一次出现之前的所有行(如果有)PATTERN1
,然后在PATTERN2
与其匹配的每一行上x
更改缓冲区。如果新的模式空间也匹配,则意味着它是第二次出现,因此它x
会变回原样q
(自动打印后)。如果它不匹配,则意味着它是第一次出现,因此它通过模式空间复制保留空间内容g
(因此现在保留缓冲区中有一条匹配的行PATTERN2
)并继续...
还有另一种方式awk
:
awk '/PATTERN1/{t=1}; t==1{print; if (/PATTERN2/){c++}}; c==2{exit}' infile
PATTERN2
仅当遇到匹配的行时才开始打印和计数匹配的行数,并在计数器到达PATTERN1
时退出。c
2
答案2
适合这项工作的工具是pcregrep
:
pcregrep -M 'PATTERN1(.|\n)*PATTERN2' file
where 选项-M
允许模式匹配多行并(.|\n)*
匹配任何字符或换行符零次或多次。
请注意,我们利用了 grep 的贪婪性。如果您想将表格pattern1打印到第一的出现pattern2,*?
则应使用非贪婪代替*
。
作为概括,要打印直到n
第 次出现的 PATTERN2:
pcregrep -M 'PATTERN1((.|\n)*?PATTERN2){n}' file
更改n
为您需要的实际数字。
答案3
只需使用标志:
$ awk '/PATTERN1/{flag=2;next} flag; /PATTERN2/{flag--}' file
a
b
c
PATTERN2
d
e
f
PATTERN2
即:当你发现PATTERN1
将标志设置为正值时;特别是 2。然后,当您找到 时PATTERN2
,将该标志减一。这样,第二场比赛后就会耗尽。在两者之间,用作在具有真值(2 或 1)时flag
触发 的值。{print $0}
答案4
如果我们告诉我们sed
很容易收集必要的行然后打印
sed -n '
/PATTERN1/{
:1
$!N
/\(PATTERN2\).*\1/!b1
p
}
' file