2013-03-31 59 views
3

所以我试图从日志行中删除嵌入的\ n而不从命令行中删除每个日志行的\ n。 我已经试过这些,他们都改变了所有\ n〜。Perl的正则表达式脚本和命令行不同

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"); 

它会产生以下与我想要的匹配的输出。

[email protected]:~/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 
    [email protected]:~/logs> 

任何人都可以解释为什么这些工作不同以及如何可以在命令行上做到这一点?

回答

4

perl -n一次处理一行文件。当它读取一行时,换行符位于字符串的末尾,而不是像正则表达式所期望的那样。您应该使用^来匹配行的开头,而不是\n

在函数版本中,您正在处理整个多行字符串。在这种情况下,换行符位于字符串的中间,并且它们与正则表达式匹配。

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~ 
+1

感谢搜索命令行perl的多行选项,并找到-0777标志,并使其正常工作。 perl -0777 -n -e's {\ n(?!2013)} {〜} mg; print'test1.txt> test1c.fix 谢谢所有 –

+0

我在这里学到了一些东西。 (来自perl --help:-0 [octal]指定记录分隔符) – ddoxey