Cha*_*esB 5 regex perl newline
我在perl oneliner上失败了一个小时,因为文件有CRLF行结尾.它在行尾有一个带有组匹配的正则表达式,并且CR包含在匹配中,使用反向引用替换是坏事.
我最终在正则表达式中手动指定了CRLF,但有没有办法让perl句柄自动换行,无论它们是什么?
原来的命令是
perl -pe 's/foo bar(.*)$/foo $1 bar/g' file.txt
Run Code Online (Sandbox Code Playgroud)
"正确"命令是
perl -pe 's/foo bar(.*)\r\n/foo $1 bar\r\n/g' file.txt
Run Code Online (Sandbox Code Playgroud)
我知道我也可以在处理之前转换行结尾,我很感兴趣如何让Perl优雅地处理这个案例.
示例文件(使用CRLF行结尾保存!)
[19:06:57.033] foo barmy
[19:06:57.033] foo baryour
Run Code Online (Sandbox Code Playgroud)
预期产出
[19:06:57.033] foo my bar
[19:06:57.033] foo your bar
Run Code Online (Sandbox Code Playgroud)
使用原始命令输出(bar开始在行开始,因为它与回车匹配):
bar:06:57.033] foo my
bar:06:57.033] foo your
Run Code Online (Sandbox Code Playgroud)
首先,让我们记住这一点
perl -ple's/foo bar(.*)\z/foo $1 bar/g' file.txt
Run Code Online (Sandbox Code Playgroud)
是接近的东西的缩写
perl -e'
while (<>) {
chomp;
s/foo bar(.*)\z/foo $1 bar/g;
print $_, $/;
}
' file.txt
Run Code Online (Sandbox Code Playgroud)
Perl使得代码可以以独立于平台的方式读/写本地文本文件.
在评论中,您询问了如何以独立于平台的方式读取/写入本地文本文件和外部文本文件.
首先,您必须禁用Perl的正常处理.
binmode STDIN;
binmode STDOUT;
Run Code Online (Sandbox Code Playgroud)
然后你将不得不处理多行结尾.
sub mychomp { (@_ ? $_[0] : $_) =~ s/(\s*)\z//; $1 }
while (<STDIN>) {
my $le = mychomp($_);
s/foo bar(.*)\z/foo $1 bar/g;
print($_, $le);
}
Run Code Online (Sandbox Code Playgroud)
而不是
perl -ple's/foo bar(.*)\z/foo $1 bar/g' file.txt
Run Code Online (Sandbox Code Playgroud)
你将会拥有
perl -e'
sub mychomp { (@_ ? $_[0] : $_) =~ s/(\s*)\z//; $1 }
binmode STDIN;
binmode STDOUT;
while (<STDIN>) {
my $le = mychomp($_);
s/foo bar(.*)\z/foo $1 bar/g;
print($_, $le);
}
' <file
Run Code Online (Sandbox Code Playgroud)
转义\R序列 Perl v5.10+;请参阅perldoc rebackslash或在线文档,它与“通用换行符”(平台无关)相匹配, 可以在此处工作(示例使用 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
Run Code Online (Sandbox Code Playgroud)
请注意,与Ether 答案的唯一区别是使用非贪婪构造(.*?而不仅仅是.*),这使得这里出现了所有的差异。
如果您想了解更多信息,请继续阅读。
背景:
这是与 相关的陷阱\R的一个例子,它源于这样一个事实:它可以匹配一个或两个字符-\r\n或者,通常是\n:[1]
使用贪婪(.*)构造 ,"my\r"-包括-\r被捕获,因为正则表达式引擎显然只回溯一个字符来查找\R,而其余字符\n 本身也满足这一要求。
相比之下,使用非贪婪(.*?)构造会导致按照预期\R匹配\r\n 序列。
[1]\R不仅仅匹配\r\nand\n:它匹配 Unicode 术语中分类为垂直空白的任何单个字符,其中还包括\v(垂直\f制表符)、(换页符)、\r(单独)以及以下 Unicode 字符:0x133 (NEXT LINE)、0x2028 (LINE SEPARATOR)、0x8232 (LINE SEPARATOR)和0x8233 (PARAGRAPH SEPARATOR)