5

我正在尝试通过 Kubuntu(GNU/Linux)中的 bash shell(GNU Bash-4.2)使用 perl(v5.14.2)来搜索和替换包含换行符的字符串,但我还没有成功。

这是我正在搜索的文本文件:

<!-- filename: prac1.html -->

hello
kitty

blah blah blah

当我使用文本编辑器 (Kate's) 的搜索和替换功能或使用正则表达式测试器 ( 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 等,以及全局模式。)

任何人都可以发现问题或提出解决方案吗?

4

2 回答 2

14

尝试这样做,我通过修改输入记录分隔符(默认为换行符)来实现这一点:

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

来自perldoc perlrun

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

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

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

特殊值 00 将导致 Perl 以段落模式 slurp 文件。任何 0400 或更高的值都将导致 Perl 将整个文件 slurp,但按照惯例,值 0777 是通常用于此目的的值。

于 2013-02-16T02:21:51.980 回答
6

问题是“-p”已经隐式地将这个循环包裹在你的“-e”周围,并且“<>”将输入分成几行,所以你的正则表达式永远不会有机会看到多于一行。

 LINE:
       while (<>) {
           ...             # your program goes here
       } continue {
           print or die "-p destination: $!\n";
       }

有关更多信息,请参见 perlrun 联机帮助页。

于 2013-02-16T01:14:40.090 回答