Perl正则表达式无法匹配带换行符\n的字符串。

5
我将尝试使用在Kubuntu(GNU/Linux)上的GNU Bash-4.2作为shell,通过perl(v5.14.2)进行搜索和替换包含换行符的字符串,但我目前还没有成功。
以下是我要搜索的文本文件:
<!-- filename: prac1.html -->

hello
kitty

blah blah blah

当我使用文本编辑器(如Kate)的查找和替换功能或正则表达式测试工具(http://regexpal.com/)时,我可以轻松地让这个正则表达式起作用:

hello\nkitty

但是在命令行中使用perl时,以下命令都没有起作用:

perl -p -i -e 's,hello\nkitty,newtext,' prac1.html
perl -p -i -e 's,hello.kitty,newtext,s' prac1.html
perl -p -i -e 's,hello.*kitty,newtext,s' prac1.html
perl -p -i -e 's,hello[\S\s]kitty,newtext,' prac1.html
perl -p -i -e 's,hello[\S\s]*kitty,newtext,' prac1.html

实际上,我变得绝望并尝试了许多其他模式,包括所有这些(“单行”和“多行”模式中的不同排列):

perl -p -i -e 's,hello\nkitty,newtext,' prac1.html
perl -p -i -e 's,hello.kitty,newtext,' prac1.html
perl -p -i -e 's,hello\nkitty,newtext,s' prac1.html
perl -p -i -e 's,hello.kitty,newtext,s' prac1.html
perl -p -i -e 's,hello\nkitty,newtext,m' prac1.html
perl -p -i -e 's,hello.kitty,newtext,m' prac1.html
perl -p -i -e 's,hello\nkitty,newtext,ms' prac1.html
perl -p -i -e 's,hello.kitty,newtext,ms' prac1.html

perl -p -i -e 's,hello[\S\s]kitty,newtext,' prac1.html
perl -p -i -e 's,hello[\S\s]*kitty,newtext,' prac1.html
perl -p -i -e 's,hello$[\S\s]^kitty,newtext,' prac1.html
perl -p -i -e 's,hello$[\S\s]*^kitty,newtext,' prac1.html
perl -p -i -e 's,hello[\S\s]kitty,newtext,s' prac1.html
perl -p -i -e 's,hello[\S\s]*kitty,newtext,s' prac1.html
perl -p -i -e 's,hello$[\S\s]^kitty,newtext,s' prac1.html
perl -p -i -e 's,hello$[\S\s]*^kitty,newtext,s' prac1.html
perl -p -i -e 's,hello[\S\s]kitty,newtext,m' prac1.html
perl -p -i -e 's,hello[\S\s]*kitty,newtext,m' prac1.html
perl -p -i -e 's,hello$[\S\s]^kitty,newtext,m' prac1.html
perl -p -i -e 's,hello$[\S\s]*^kitty,newtext,m' prac1.html
perl -p -i -e 's,hello[\S\s]kitty,newtext,ms' prac1.html
perl -p -i -e 's,hello[\S\s]*kitty,newtext,ms' prac1.html
perl -p -i -e 's,hello$[\S\s]^kitty,newtext,ms' prac1.html
perl -p -i -e 's,hello$[\S\s]*^kitty,newtext,ms' prac1.html

我也尝试了使用 \r \r\n \R \f \D 等不同的换行符,同时也在全局模式下尝试过。 有人能发现问题或提出解决方案吗?
2个回答

14

通过修改 输入记录分隔符(默认为换行符),尝试执行此操作:

perl -i -p00e 's,hello\nkitty,newtext,' prac1.html

来自perldoc perlrun

-0[八进制/十六进制]

将输入记录分隔符($/)指定为八进制或十六进制数字。如果没有数字,则空字符是分隔符。其他开关可以在数字之前或之后。例如,如果您有一个可以打印以空字符结尾的文件名的 find 版本,则可以这样说:

find . -name '*.orig' -print0 | perl -n0e unlink

特殊值00会导致Perl以段落模式读取文件。 任何0400或以上的值都会使Perl整个读取文件,但按照惯例,值0777通常用于此目的。


1
我已经使用Perl编程20年了,但我从未听说过“段落模式”。谢谢! - Bluby
1
感谢 @sputnick 和 @Bluby!以下是帮助我理解 Perl 手册材料的一些网站:Perl 的特殊变量(输入和输出记录分隔符等)“钻石”操作符空“钻石”操作符(<>) - zeroparallax

6
问题在于“-p”已经隐式地将循环包装在您的“-e”周围,“<>”正在将输入拆分为行,因此您的正则表达式永远没有机会查看超过一行。
 LINE:
       while (<>) {
           ...             # your program goes here
       } continue {
           print or die "-p destination: $!\n";
       }

请参见perlrun的man页获取更多信息。

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