2013-03-31 100 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