所以我试图从日志行中删除embedded \ n,而不从命令行中删除每个日志行的\ n。 我尝试了这些,他们都改变了所有\ n到〜。
cat test1.txt | perl -n -e 's{\n(?!2013)}{~}mg;print' > test1a.fix
perl -n -e 's{\n(?!2013)}{~}mg;print' test1.txt > test1b.fix
所有人都忽略了背后的负面看法。
test1.txt包含
2013-03-01 12:23:59,1
line2
line3
2013-03-01 12:23:59,4
test1a.fix和test1b.fix包含
2013-03-01 12:23:59,1~line2~ line3~2013-03-01 12:23:59,4
但是我使用这个脚本想出了正则表达式。
#!/usr/bin/perl
use warnings;
use strict;
sub test {
my ($str, $expect) = @_;
my $mod = $str;
$mod =~ s{\n(?!2013)}{~}mg;
print "Expecting '$expect' got '$mod' - ";
print $mod eq $expect ? "passed\n" : "failed\n";
}
test("2013-03-01 12:23:59,line1
line2
line3
2013-03-01 12:23:59,line4", "2013-03-01 12:23:59,line1~line2~ line3
2013-03-01 12:23:59,line4");
并生成以下符合我想要的输出。
sfager@linux-sz05:~/logs> ./regex_test.pl
Expecting '2013-03-01 12:23:59,line1~line2~ line3
2013-03-01 12:23:59,line4' got '2013-03-01 12:23:59,line1~line2~ line3
2013-03-01 12:23:59,line4' - passed
sfager001@linux-sz05:~/logs>
任何人都可以解释为什么这些工作方式不同以及如何在命令行上完成这项工作?
答案 0 :(得分:4)
perl -n
一次处理一行文件。当它读取一行时,换行符位于字符串的末尾,而不是您的正则表达式所期望的开头。您应该使用^
来匹配行的开头而不是\n
。
在函数版本中,您将立即处理整个多行字符串。在这种情况下,换行符位于字符串的中间,并且它们与正则表达式匹配。
答案 1 :(得分:2)
您的命令行程序一次只能看到一条“输入记录”(a.k.a.行)。 我可以通过拼写输入记录分隔符变量$ /。
来使您的示例正常工作perl -n -e '$/=undef; s{\n(?!2013)}{~}mg;print' test1.txt > test1c.fix
这将重新定义每个“行”作为整个输入,实际上让它更像你的脚本。
cat test1c.fix
2013-03-01 12:23:59,1~line2~ line3
2013-03-01 12:23:59,4~