例如
xyz
A1
B1
C1
D1
End
End
End
X1
X2
X3
Done
我想提取 xyz 到结束模式之间的所有字符串。所以输出应该是
xyz
A1
B1
C1
D1
End
End
End
答案1
方法一
perl -l -0777ne 'print /^(xyz.*?^End$(?:\nEnd$)*)/ms' yourfile
在职的
- 读取文件,使其显示为一个很长的字符串,然后可以使用适当的正则表达式将其拆开。本例中的正则表达式是:
- 在行(不一定是文件)的开头查找 xyz。
- 单独查找一行上最近的 End,然后查找尽可能多的连续行。
方法2
perl -lne '
next unless /xyz/ ... eof;
last if !/End/ and $flag;
$flag ||= 1 if /End/;
print;
' yourfile
在职的
- 在这里,我们以每行为基础操作 Perl 并设置一个小型状态机。
- 拒绝文件的任何非范围部分。
- 一旦我们输入正确的范围,我们就会打印所有行,直到到达 /End/ 行。那时我们设置了标志。
- 然后,当我们看到第一条非/End/行时,我们就会爆发。
方法3
sed -e '
/xyz/!d
:a
$q;N
/\nEnd$/!ba
:b
n
/End/bb
d
' yourfile
在此方法中,我们操作第一个 do-while 循环 (:a),它将累积从 /xyz/ 到 /End/ 的行。
第二个 do-while 循环 (:b) 将打印行,直到下一行恰好是 /End/。
方法4
sed -e '
/xyz/,/End/!d
H;/xyz/h;/End/!d
:a
$q;N
/\(.*\)\n\1$/!{g;q;}
s/.*\n//;H
ba
' yourfile
使用这种方法,我们首先选择正确的范围,然后将该范围数据存储在保存空间中。 do-while 循环 (:a) 设置为增量追加到保留空间,而下一行恰好是 /End/。
结果
xyz
A1
B1
C1
D1
End
End
End
答案2
这是一种pcregrep
擅长的工作:
pcregrep -M 'xyz(.|\n)*End' file
请注意,它非常贪吃,直到最后才吃掉所有东西结尾,包括其他结尾s。
答案3
Perl 来救援:打印第一行xyz
和最后一行之间的所有行End
:
perl -ne '
$inside = 1 if /^xyz$/;
$seen_end = 1 if $inside && /^End$/;
push @buff, $_ if $inside;
print splice @buff if /^End$/ && @buff;
' input-file
从第一次出现开始xyz
,我们开始将所有行推入缓冲区。一旦End
遇到,我们输出并清除缓冲区(参见拼接),但我们继续将行推入缓冲区,以防End
稍后出现另一个行。
答案4
awk解决方案:
awk '/xyz/,/End/{ print $0; n=NR }($0=="End" && n && NR>n && NR-n++ == 1)' file
输出:
xyz
A1
B1
C1
D1
End
End
End
/xyz/,/End/
- 记录范围,从xyz
到End
n=NR
- 捕获记录编号(在范围匹配上 - 最终将包含该范围的最后一条记录的编号)