匹配除关键字之外的标识符

时间:2012-08-17 01:11:28

标签: regex perl

我需要在文本文件中找到标识符:

但如果标识符是关键字,我不想要匹配。例如,如果我将“for”作为关键字,请执行以下操作:

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

我应该得到:

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

我研究了前瞻性断言,但我无法使其发挥作用:

$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”?

3 个答案:

答案 0 :(得分: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";
    }
}

答案 1 :(得分:1)

您需要锚定以确保您匹配整个字(潜在标识符)。对于第一个近似值,/\b(?!(?:for|while|do)\b)[A-Za-z_][A-Za-z0-9_]*\b/实际上做了你想要的。

答案 2 :(得分: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+";

(这也解决了“完成”与“执行”不相同的问题。)