我在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 rebackslash
或documentation 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/