2012-08-17 92 views
1

我需要找到標識符在一個文本文件標識符:匹配除了關鍵字

但我不希望有一個匹配,如果標識符是一個關鍵詞。舉例來說,如果我有「爲」爲關鍵詞,在下面:

for (i=0 ; i< max ; i++) 

我應該得到:

Found: i 
Found: i 
Found: max 
Found: i 

我看着先行斷言,但我wan't能使其工作:

$IDENTIFIER="(?!(for|while|do))[a-zA-Z_]+[a-zA-Z0-9_]*" 
    while ($entireFile =~ /($IDENTIFIER)/g) 
    { 
      print "Found ($1)" . "\n"; 
    } 

我得到:

Found: or 
Found: i 
Found: i 
Found: max 
Found: i 

這不是我想要的安靜!我明白爲什麼我會得到「或」,但我怎樣才能讓它變得更聰明並完全排除「for」?

回答

1

您需要錨定,以確保你相匹配的整個字(潛在的標識符)。第一次近似,/\b(?!(?:for|while|do)\b)[A-Za-z_][A-Za-z0-9_]*\b/實際上做你想要的。

0

因爲您可能正在查看評論,所以您不能只查找看起來像標識符的內容。您只能在標識符可能出現的地方查找標識符。在「f」之後不能立即出現標識符。換句話說,真正的問題是你沒有解決問題。

您沒有顯示您的問題,因此我們無法幫助您解決問題。我們可以直接回答你的問題一味:

$ID_START = "[a-zA-Z_]"; 
$ID_CONT = "[a-zA-Z0-9_]"; 
$IDENT = "(?<!$ID_START)(?<!$ID_CONT)(?!(?:for|while|do)(?!$ID_CONT))$ID_START$ID_CONT+"; 

(這也解決了「做」的問題並不一樣對待「做」。)

1

即使在Perl,清晰度問題。我建議將關鍵詞過濾器中的詞語發現正則表達式分開,以使測試更易於閱讀,更新等。另外,如果要過濾掉大量關鍵字,則製作單獨的列表比將它們填充到一個常規表達。這裏有一個例子:

use strict; 
use warnings; 

my $entireFile = "for (i=0 ; i< max ; i++)"; 
my @KEYWORDS = ('for', 'while', 'do'); 

while ($entireFile =~ /([a-zA-Z_][a-zA-Z0-9_]*)/g) 
{ 
    my $is_keyword = 0; 
    for my $keyword (@KEYWORDS) 
    { 
     if ($1 eq $keyword) 
     { 
      $is_keyword = 1; 
     } 
    } 
    if (not $is_keyword) 
    { 
     print "Found ($1)" . "\n"; 
    } 
} 
+3

我同意這個答案的一些意圖,但是如果你的代碼樣本沒有顯着*比原來糟糕的性能,這將有所幫助。可以使用散列來測試集合成員資格('@關鍵字{$ _} ++ for @ KEWYWORDS',然後'if(!$ keywords {$ 1})')或使用單獨的正則表達式。不要對'eq'使用循環測試,它甚至不會花費早期的時間來解決問題,12行代碼可以在1到3之間完成。 – hobbs 2012-08-17 02:37:38

+0

謝謝你hobbs!我也在這裏學習。 雖然你的描述很清楚,但這裏是一個完整的重寫: 'my $ entireFile =「for(i = 0; i 2012-08-18 01:05:51

+0

看起來不錯:) – hobbs 2012-08-18 01:12:17