正如Jim Davis 指出的那样,$ 匹配字符串的结尾或\n 字符之前(使用/m 选项)。 (参见perlre Perldoc 页面的Regular Expressions 部分。使用g 修饰符允许它继续匹配。
多行 Perl 正则表达式(即,其中包含换行符的 Perl 正则表达式,即使它只在行尾出现一次)会导致大多数 Perl 程序员在处理问题时遇到的各种复杂情况。
像这样:
open my $file_handle, "<:crlf", $file...
如果这实际上是 Linux/Mac 系统上的 Windows 文件,这将自动将 \r\n 字符替换为 \n。如果这是一个普通的 Linux/Mac 文本文件,它什么也不做。其他明显的解决方案是不使用 Windows(rim shot!)。
当然,在您的情况下,首先使用 chomp 会完成以下操作:
$cat file
line one
line two
line three
line four
$ perl -pe 'chomp;s/$/addthis::/g`
line oneaddthis::line twoaddthis::line threeaddthis::line fouraddthis::
chomp 删除了\n,所以现在,当行打印出来时你看不到它。嗯……
$ perl -pe 'chomp;s/$/addthis/g;print "\n";
line oneaddthis
line twoaddthis
line threeaddthis
line fouraddthis
这行得通!而且,你的一个班轮只是有点难以理解。
另一件事是采用 Damian Conway 在他的书 Perl Best Practices 的第 12 章中推荐的更现代的方法:
使用\A 和\z 作为字符串边界锚。
即使您不采用以前始终使用 /m 的做法,使用 ^ 和 $ 及其默认含义也是一个坏主意。当然,您知道 ^ 和 $ 在 Perl 正则表达式1 中的实际含义。但是那些阅读或维护您的代码的人会知道吗?还是他们更有可能以前面描述的方式误解这些元字符?
Perl 提供的标记总是——并且明确地——表示“字符串的开头”和“字符串的结尾”:\A 和 \z(大写的 A,但小写的 z)。无论 /m 是否处于活动状态,它们都表示“字符串的开始/结束”。它们的意思是“字符串的开始/结束”,不管读者认为 ^ 和 $ 是什么意思。
如果你听从了康纳威的建议,并且这样做了:
perl -pe 's/\z/addthis/mg' myfile.txt
您会看到您的短语 addthis 仅添加到每一行的末尾:
$cat file
line one
line two
line three
line four
$ perl -pe `s/\z/addthis/mg` myfile.txt
line one
addthisline two
addthisline three
addthisline four
addthis
看看效果如何。 addthis 被添加到每一行的最后! ...就在该行的\n 字符之后。
玩够了,回去工作吧。 (等等,今天是总统日。这是一个带薪假期。今天没有工作,当然除了我承诺在星期二早上之前完成的所有事情)。
希望这有助于您了解正则表达式有多么有趣,以及为什么这么多人决定学习 Python。
1. 知道^ 和$ 在Perl 中的真正含义吗?嗯,当然我会。我已经用 Perl 编程了几十年。是的,我知道所有这些东西。 (自我注意:$ 显然不是我一直认为的意思。)