一行打印两个图案之间的所有线条

One-liner to print all lines between two patterns

使用一行 Perl 代码,打印两个模式之间的所有行(不包括带有模式的行)的最短方法是什么?

如果这是file.txt:

aaa
START
bbb
ccc
ddd
END
eee
fff

我要打印这个:

bbb
ccc
ddd

我可以使用类似这样的方式完成大部分工作:

perl -ne 'print if (/^START/../^END/);'

不过,这包括 STARTEND 行。

我可以这样完成工作:

perl -ne 'if (/^START/../^END/) { print unless (/^(START)|(END)/); };' file.txt

但这似乎是多余的。

我真正想做的是像这样使用后向和前向断言:

perl -ne 'print if (/^(?<=START)/../(?=END)/);' file.txt

但这不起作用,我想我的正则表达式有点不对劲。

这些只是我尝试过的一些没有产生输出的变体:

perl -ne 'print if (/^(?<=START)/../^.*$(?=END)/);' file.txt
perl -ne 'print if (/^(?<=START)/../^.*(?=END)/);' file.txt
perl -ne 'print if (/^(?<=START)/../(?=END)/);' file.txt
perl -ne 'print if (/^(?<=START)/../.*(?=END)/);' file.txt
perl -ne 'print if (/^(?<=START)/../^.*(?=END)/);' file.txt
perl -ne 'print if (/^(?<=START)/../$(?=END)/);' file.txt
perl -ne 'print if (/^(?<=START)/../^(?=END)/);' file.txt
perl -ne 'print if (/^(?<=START)/../(?=^END)/);' file.txt
perl -ne 'print if (/^(?<=START)/../.*(?=END)/s);' file.txt

对此设置单行限制似乎有点武断,但这是一种方法:

$ perl -wne 'last if /^END/; print if $p; $p = 1 if /^START/;' file.txt
perl -e 'print split(/.*START.|END.*/s, join("", <>))' file.txt

perl -ne 'print if /START/../END/' file.txt | perl -ne 'print unless $.==1 or eof'

perl -ne 'print if /START/../END/' file.txt | sed -e '$d' -n -e '1\!p'

读取整个文件,匹配并打印。

perl -0777 -e 'print <> =~ /START.*?\n(.*?)END.*?/gs;' file.txt

如果一个人在线,可能会在 START|END 之后掉落 .*?。 然后删除 \n 以在段之间留空行。


读取文件,按START|END分割行,打印@F的每个奇数

perl -0777 -F"START|END" -ane 'print @F[ grep { $_ & 1 } (0..$#F) ]' file.txt

使用 END { } 块进行额外处理。将 }{ 用于 END { }

perl -ne 'push @r, $_ if (/^START/../^END/); }{ print "@r[1..$#r-1]"' file.txt

有效,因为它仅代表文件中的单个此类段。

我不明白你为什么如此坚持使用环视,但这里有几种方法可以做到这一点。

perl -ne 'print if /^(?=START)/../^(?=END)/'

这会找到终止符,但不会实际匹配它们。满足前瞻的零长度匹配被匹配。

您的回顾没有工作,因为它试图在同一行上找到 ^ 行的开头和它之前的 START ,这显然永远不会匹配。将 ^ 分解为零宽度断言,它将起作用:

perl -ne 'print if /(?<=^START)/../(?<=^END)/'

正如@ThisSuitIsBlackNot 在评论中所建议的那样,您可以使用序列号来省略 STARTEND 标记。

perl -ne '$s = /^START/../^END/; print if ($s>1 && $s !~ /E0/)'

lookarounds 没有提供任何有用的东西,所以我没有完全开发这些示例。如果您更关心使用环视而不是代码可维护性和执行速度,则可以将其调整为上面的环视示例之一。