2012-08-17 154 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