我在perl oneliner上head了一个小时,但失败了,因为该文件的尾行是CRLF。它的正则表达式在行的末尾具有组匹配项,并且CR被包含在匹配项中,使用后向引用进行替换会造成不良后果。

我最终在正则表达式中手动指定了CRLF,但是有没有办法让perl句柄自动换行,无论它们是什么?

原始命令是

perl -pe  's/foo bar(.*)$/foo $1 bar/g' file.txt

“正确”命令是
perl -pe  's/foo bar(.*)\r\n/foo $1 bar\r\n/g' file.txt

我知道我也可以在处理之前转换行尾,我对如何让Perl优雅地处理这种情况感兴趣。

示例文件(保存CRLF行结尾!)
[19:06:57.033] foo barmy
[19:06:57.033] foo baryour

预期产量
[19:06:57.033] foo my bar
[19:06:57.033] foo your bar

使用原始命令进行输出(小节在行的开头,因为它与回车符匹配):
bar:06:57.033] foo my
bar:06:57.033] foo your

最佳答案

\R转义序列 Perl v5.10 + ;请参阅perldoc rebackslashdocumentation online,它可以与“通用换行符”(平台无关)匹配,在这里可以工作(示例使用Bash创建多行输入字符串):

$ printf 'foo barmy\r\nfoo baryour\r\n' | perl -pe 's/foo bar(.*?)\R/foo $1 bar\n/gm'
foo my bar
foo your bar

请注意,与Ether's answer的唯一区别是使用了非贪心的构造(.*?而不是.*),这使得所有区别都在这里。

如果您想了解更多,请继续阅读。

背景:

它是与\R相关联的陷阱的一个示例,该陷阱源于它可以匹配一个或两个字符-\r\n或通常是\n的事实:[1]

使用贪婪的(.*)构造,可以捕获"my\r"(包括\r),因为正则表达式引擎显然仅回溯了一个字符来查找\R,其余的\n本身也可以满足要求。

相比之下,使用非贪婪的(.*?)构造会使\R符合预期的\r\n序列。

[1] \R不仅匹配\r\n\n,而且还匹配:它匹配以Unicode术语归类为垂直空格的任何单个字符,其中还包括\v(垂直标签),\f(换页),\r(本身),以及以下Unicode字符:0x133 (NEXT LINE)0x2028 (LINE SEPARATOR)0x8232 (LINE SEPARATOR)0x8233 (PARAGRAPH SEPARATOR)

关于regex - 如何制作一个perl单线 “line-endings agnostic”,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19682400/

10-12 17:50
查看更多