我终于想出了如何将文本附加到文件中每一行的末尾:
perl -pe 's/$/addthis/' myfile.txt
但是,当我尝试学习 Perl 以经常使用正则表达式时,我无法弄清楚为什么以下 perl 命令将文本“addthis”添加到每行的末尾和开头:
perl -pe 's/$/addthis/g' myfile.txt
我认为无论正则表达式匹配使用什么修饰符,'$' 都匹配行尾,但我想这是错误的?
摘要: 对于您正在做的事情,请删除/g
它,使其仅在换行符之前匹配。/g
告诉它在换行符之前和字符串末尾(换行符之后)匹配。
如果没有/m
修饰符,$
将在换行符之前(如果它出现在字符串末尾)或字符串末尾匹配。例如,如果同时使用"foo"
and "foo\n"
,则$
将在 之后匹配foo
。"foo\nbar"
但是,它会在 之后匹配,bar
因为嵌入的换行符不在字符串的末尾。
使用/g
修饰符,您将获得所有$
匹配的位置——所以
s/$/X/g;
会取一条线"foo\n"
,然后把它变成"fooX\nX"
.
侧边栏:
修饰符/m
将允许$
匹配出现在字符串末尾之前的换行符,以便
s/$/X/mg;
将转换"foo\nbar\n"
为"fooX\nbarX\nX"
.
正如吉姆戴维斯指出的那样,$
匹配字符串的结尾或\n
字符之前(带有/m
选项)。(参见perlre Perldoc 页面的正则表达式部分。使用修饰符允许它继续匹配。g
多行 Perl 正则表达式(即,其中包含换行符的 Perl 正则表达式,即使它只在行尾出现一次)会导致大多数 Perl 程序员遇到问题处理的各种复杂情况。
如果您一次读取一行文件,请始终在对该行chomp
执行任何操作之前使用。g
使用限定符时,这将解决您的问题。
如果您在 Linux/Mac 上读取来自 Windows 的文件,则可能会出现更多问题。在这种情况下,您将同时具有\r
和\n
字符。正如我最近在尝试调试程序时发现的那样,该\r
字符不会被chomp
. 我现在确保我总是打开我的文本文件进行阅读
像这样:
open my $file_handle, "<:crlf", $file...
如果这实际上是 Linux/Mac 系统上的 Windows 文件,这将自动替换\r\n
字符。\n
如果这是一个普通的 Linux/Mac 文本文件,它什么也不做。其他明显的解决方案是不使用 Windows(边缘拍摄!)。
当然,在您的情况下,首先使用 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 编程了几十年。是的,我知道所有这些东西。(自我注意:$
显然并不意味着我一直认为的意思。)
一种解决方法:
perl -pe 's/\n/addthis\n/'
不需要g
修饰符:正则表达式逐行处理。