2014-04-17 74 views
0

我正在實現一個腳本,該腳本將檢查給定正則表達式模式的一個或多個文件,並在文件包含任何匹配時提醒用戶。但是,我希望能夠允許用戶在文件內部指定異常(即不會被檢查的部分文件)。我想實現這個的方式是在文件中使用BEGIN:EXCEPTION和END:EXCEPTION標記。腳本現在工作的方式如下:匹配BEGIN和END標記內部不包含的模式

(在$假設文件內容_)

my $re_dirty = /hello world/; # Simple example 
if($re_dirty) { 
    # alert that the pattern was found in the file 
} 

我試圖將此更改爲以下幾點:

my $re_dirty = /hello world/; # Simple example 
my $begin_token = 'BEGIN:EXCEPTION'; 
my $end_token = 'END:EXCEPTION'; 
if($re_dirty && $_ !~ /${begin_token}.*${re_dirty}.*${end_token}) { 
    # alert that the patter was found and was not in an exception block 
} 

然而,這顯而易見的問題:
1.如果模式前後有異常,但模式本身不在異常內,則匹配。
2.如果模式在文件中兩次,但它們中只有一個在異常塊中,它將不匹配。
3.可能更多的問題?

一對夫婦有解釋性說明的:
1.異常可以跨越多行。
2.每個文件可以有多個異常塊。

回答

1

我會做這樣的事情:

(my $portion = $_) =~ s/${begin}.*?${end}//gs; # reject anything inside begin/end blocks 

if ($portion =~ $re_dirty) { 
    # do stuff 
} 

這樣,你在$部分僅獲得文件的相關部分(那些開始/結束標記)。然後你可以在相關部分執行標準的正則表達式匹配...
注意使用'?'改性劑,以避免從第一令牌開始到最後結束令牌匹配...

+0

我可能是錯的在此,但如果文件中有多個開始和結束異常標記,這不會有問題嗎?或者是替換正則表達式「貪婪」,因爲它會匹配它看到的第一個結束標記? – Kyle

+0

@Kyle如果你使用'。*?'這意味着它是非貪婪的,儘可能少匹配。相反,可能會說。 – TLP

+0

@TLP謝謝你的澄清 – Kyle

0

你可以一個布爾添加到您的邏輯:

my $begin_token = 'BEGIN:EXCEPTION'; 
my $end_token = 'END:EXCEPTION'; 
my $bool = 0; 
$bool = 1 if $begin_token; 
$bool = 0 if $end_token 

,那麼你可以,如果$ BOOL是1或0跳過或不測試代碼的部分

3

您可以在標量上下文使用flip-flop (range operator)

if (/$begin/ .. /$end/) { 
    if (/$re_dirty/) { 
     # do stuff 
    } 
} 

範圍內運營商的這種特殊用法將返回false(如一個語句),直到左側返回true,之後它將返回true直到右側返回true。

當然,使用這種方法,您應該逐行讀取文件模式。但總體而言,這是一個更好的方法,關於內存使用情況。

編輯:

如果你想對陣多外這樣的塊的匹配,你必須先蒐集相關線路爲多行字符串:

my @outside; 
my $content; 
while (<$file>) { 
    if (/$begin/ .. /$end/) {  # if inside tags 
     if (defined $content) {  # if not empty 
      push @outside, $content; # store the scalar into array 
      undef $content;   # reset variable 
     } 
    } else { 
     $content .= $_;    # store into scalar 
    } 
} 
push @outside, $content if defined $content; 

for my $portion (@outside) { 
    if ($portion =~ /$re_dirty/) {  # check for multiline matches 
     # do stuff 
    } 
} 
+0

這是否支持跨越多行的異常? – Kyle

+1

+1,我記得你在其他地方有關awk的討論中提到了觸發器操作符,現在我想發佈這個解決方案,但是你打敗了我:-) –

+0

@Kyle這適合line-by在線閱讀文件,而不是多行匹配。 – TLP