如何在命令行中使用Perl风格的正则表达式匹配多行模式?

4

我经常使用正则表达式来转换文本。

为了从命令行转换大型文本文件,Perl让我这样做:

perl -pe < in.txt > out.txt

但这需要逐行进行。有时候,我想匹配多行内容。

在命令行中,我该如何实现这个目标?


1
我相信Perl可以满足你的需求。你可以要求它使用除换行符以外的记录分隔符,或者它可以在空行处或使用固定的记录大小拆分文件。或者,如果你的文件大小合理,你可以将其全部读入内存,并从那里处理它。除非你更多地解释你的应用程序,否则我无法确定什么是最好的方法。 - Borodin
请返回已翻译的文本:请参阅http://docstore.mik.ua/orelly/unix/sedawk/ch06_01.htm - Fabricator
1
具体来说,perl -0777 -pe ... 并不是基于逐行处理的。 :) - Amadan
要求我们推荐或寻找工具、库或喜爱的外部资源的问题,因为它们往往会吸引有意见的答案和垃圾邮件,所以在 Stack Overflow 上是不适合的。相反,请描述问题以及已经采取的解决方案。 - Jim Garrison
1
可能是Perl命令行多行替换的重复问题。 - Cees Timmerman
2个回答

7
为了不逐行处理而抓取文件,请使用-0777开关:
perl -0777 -pe 's/.../.../g' in.txt > out.txt

perlrun #命令开关 中所述:

特殊值-00将使Perl以段落模式读取文件。任何值-0400或更高都会导致Perl整个读取文件,但通常使用值-0777来实现此目的。

显然,对于大文件,这种方法可能效果不佳,此时您需要编写某种类型的缓冲区来进行替换。 但如果没有关于您意图的真实信息,我们无法给出更好的建议。

1

跨越行边界的Grepping

所以你想要跨越行边界进行Grepping...

你很可能已经安装了pcregrep。正如你所知,PCRE代表Perl兼容正则表达式,该库绝对是Perl风格,但不完全相同。

要匹配多行,您必须打开多行模式-M,这与(?m)不同

运行pcregrep -M "(?s)^b.*\d+" text.txt

在此文本文件上:

a
b
c11

输出结果将是:
b
c11

whereas grep would return empty.
摘自文档:

-M, --multiline 允许模式匹配多行。当给出此选项时,模式可以包含文字换行符和^和$字符的内部出现。成功匹配的输出可能由多行组成,其中最后一行是匹配结束的行。如果匹配的字符串以一个新行序列结尾,则输出在该行的末尾结束。

设置此选项时,PCRE库以“多行”模式调用。可以匹配的行数有限,这是由于pcregrep在扫描输入文件时缓冲的方式所限制的。但是,pcregrep确保至少有8K个字符或文档的剩余部分(以较短者为准)可用于向前匹配,并且类似地保证前面的8K个字符(或所有先前字符,如果少于8K)对于回顾断言是可用的。当按行读取输入时,此选项不起作用(请参见--line-buffered)。


那听起来差不多就是我想要的,只是我还需要替换部分。 - JnBrymn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接