$和Perl的全局正则表达式修饰符

时间:2013-02-18 16:33:10

标签: regex perl

我终于想出了如何将文本附加到文件中每行的末尾:

perl -pe 's/$/addthis/' myfile.txt

然而,由于我正在尝试使用Perl进行常规正则表达式使用,我无法弄清楚为什么以下perl命令将文本'addthis'添加到结尾并开始每一行:

perl -pe 's/$/addthis/g' myfile.txt

我认为'$'匹配线的末尾,无论使用什么修饰符进行正则表达式匹配,但我猜这是错误的?

3 个答案:

答案 0 :(得分:10)

摘要:对于您正在做的事情,请删除/g,使其仅在换行符之前与匹配。 /g告诉它在字符串末尾的换行符之前(换行符之后)匹配。

如果没有/m修饰符,$将在换行符之前(如果它出现在字符串的末尾)或字符串的末尾匹配。例如,对于"foo""foo\n"$将在foo之后匹配。但是,对于"foo\nbar",它会在bar之后匹配,因为嵌入换行符不在字符串的末尾。

使用/g修饰符,您将获得$匹配的所有位置 - 所以

s/$/X/g;

将采用"foo\n"之类的行并将其转换为"fooX\nX"

<强>侧栏: /m修饰符将允许$匹配字符串结尾前出现的换行符,以便

s/$/X/mg;

会将"foo\nbar\n"转换为"fooX\nbarX\nX"

答案 1 :(得分:5)

正如Jim Davis所指出的那样,$匹配字符串的结尾或\n字符(/m选项之前)。 (请参阅Regular Expressions Perldoc页面的perlre部分。使用g修饰符可以继续匹配。

多行Perl正则表达式(即Perl正则表达式中包含新行符号,即使它只出现在行尾的一次)会导致大多数Perl程序员遇到问题处理的各种复杂情况。

  • 如果您一次只读取一行文件,请在使用该行 ANYTHING 之前使用chomp。在使用g限定符时,这可以解决您的问题。

  • 如果您正在阅读来自Windows的Linux / Mac上的文件,则可能会出现更多问题。在这种情况下,您将同时拥有\r\n字符。正如我最近在尝试调试程序时发现的那样,\r并未删除chomp字符。我现在确保我总是打开我的文本文件进行阅读

像这样:

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

有效!并且,你的一个班轮只是略微难以理解。


另一件事是在他的书Perl Best Practices的第12章中采用Damian Conway建议的更多现代方法:

  

使用\A\z作为字符串边界锚点。

     

即使你没有采用以前总是使用/ m的做法,使用^和$的默认含义也是个坏主意。当然,你知道在Perl正则表达式 1 中^和$实际意味着什么。但阅读或维护代码的人会知道吗?或者他们更有可能以前面描述的方式误解这些元字符?   Perl提供的标记始终 - 并且明确地 - 表示“字符串的开头”和“字符串的结尾”:\ A和\ z(大写字母A,但是小写字母z)。它们的意思是“字符串的开始/结束”,无论/ m是否有效。它们的意思是“字符串的开始/结束”,无论读者如何思考^和$ mean。

如果您遵循Conaway的建议,并且这样做了:

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编程了几十年。是的,我知道这些东西。 (自我注意:$显然并不代表我一直认为的意思。)

答案 2 :(得分:0)

解决方法:

perl -pe 's/\n/addthis\n/' 

不需要g修饰符:正则表达式逐行处理。