我想打印两个模式之间的输出,第一个模式应该是文件中的第二次匹配。
例子 -
test.txt
start one
text_1
end
start two
text_2
end
start three
text_3
end
这里第一个模式是start
,第二个模式是end
。模式start
应该是文件中的第二次模式匹配。那么输出应该是
start two
text_2
end
答案1
使用awk
,可以轻松扩展到任意第 n条记录:
awk '/start/ && ++n == 2, /end/' < file
将打印从第二次出现start
到第一次出现的行end
。
打印第二个start
记录end
(如果有start
, start
,end
序列将会有所不同):
awk '
/start/, /end/ {
if (!seen) {seen = 1; n++}
if (n == 2) print
if (/end/) seen = 0
}' < file
或者:
awk '
!inside && /start/ {inside = 1; n++}
!inside {next}
n == 2
/end/ {inside = 0}' < file
答案2
和sed
sed -n '/start/,/end/n;/start/,/end/{p;/end/q}' file
解释:
-n
抑制输出- 首先
/start/,/end/n
提取第一个开始到结束块,但不执行任何操作(通过n
) - 然后进行第二个从开始到结束的块
/start/,/end/
打印,并在到达结束后立即退出p;/end/q
答案3
在这种特殊情况下 - 当输入仅由/start/,/end/
块组成时,您可以简单地执行以下操作
sed '1,/end/d;//q' infile
如果这些块之间还有其他行(不匹配end
)那么
sed '1,/end/d;/start/,/end/!d;/end/q' infile
对于更一般的情况,当要提取的块是n
您可以运行的块时:
n=5
awk -vc=$n '/start/{i++};{if (i==c){print;if (/end/){exit}}}' infile
答案4
sed -ne '
/^start/,/^end/!d; # skip non-interesting block
/^start/H; # increment hold counter
G;/\n.*\n.*\n/!d; # check if 2nd block reached?
P;/^end/q; # we"re in 2nd block so print & quit on /end/
' yourfile
perl -l -0777ne 'print+(/^start.*?\nend[^\n]*$/msg)[1]' yourfile