正则表达式匹配perl变量

时间:2012-09-15 21:11:14

标签: regex perl variables

我目前正在学习正则表达式,我正在尝试创建一个正则表达式来匹配Perl中的任何合法变量名称。

这是我到目前为止所写的内容:

^\$[A-Za-z_][a-zA-Z0-9_]*

唯一的问题是特殊符号的正则表达式返回true,例如字符串 $ a& 将返回true。

我做错了什么?

谢谢! ROTEM

3 个答案:

答案 0 :(得分:8)

解析Perl很困难,而且变量是什么和不是变量的规则是复杂的。如果您尝试解析Perl,请考虑使用PPI。它可以解析Perl程序并执行诸如查找所有变量之类的操作。 PPI是perlcritic用来完成工作的原因。

如果你想尝试去做,这里有一些需要考虑的优势......

$^F
$/
${^ENCODING}
$1
$élite           # with utf8 on
${foo}
*{foo} = \42;
*{$name} = \42;  # with strict off
${$name} = 42;   # with strict off

当然其他的印记@%*。并检测单个带引号的字符串中是否有内容。哪种方式强烈鼓励你使用PPI,而不是自己尝试。

如果你想练习,现实的做法是将变量从较大的字符串中拉出来,而不是完全匹配。

# Match the various sigils.
my $sigils         = qr{ [\$\@\%*] }x;

# Match $1 and @1 and so on
my $digit_var      = qr{ $sigils \d+ }x;

# Match normal variables
my $named_var      = qr{ $sigils [\w^0-9] \w* }x;

# Combine all the various variable matches
my $match_variable = qr{ ( $named_var | $digit_var ) }x;

这使用()捕获运算符来获取变量。它还使用/x修饰符使正则表达式更易于阅读,并使用其他分隔符来避免leaning toothpick syndrome。使用\w代替A-Z可确保在utf8启用时拾取Unicode字符,并在关闭时不会拾取它们。最后,qr用于构建正则表达式。填补空白留作练习。

答案 1 :(得分:2)

最后你需要一个$,否则它只是尽可能匹配而忽略其余的。所以它应该是:

^\$[A-Za-z_][A-Za-z0-9]*$

答案 2 :(得分:0)

我需要解决这个问题才能创建一个简单的源代码分析器 此子例程从代码的输入部分

中提取Perl用户变量
sub extractVars {
    my $line = shift;
    chomp $line;
    $line =~ s/#.*//;       # Remove comments
    $line =~ s/\s*;\s*$//;  # Remove trailing ;
    my @vars = ();
    my $match = 'junk';
    while ($match ne '') {
        push @vars, $match if $match ne 'junk';
        $match = ''; 
        if ($line =~ s/(
                [\@\$\%]            # $@%
                {?                  # optional brace
                \$?                 # optional $
                [\w^0-9]            # begin var name
                [\w\-\>\${}\[\]'"]* # var name
                [\w}\]]             # end var name
                |
                [\@\$\%]            # $@%
                {?                  # optional brace
                \$?                 # optional $
                [\w^0-9]            # one letter var name
                [}\]]?              # optional brace or bracket
                )//x) {
            $match = $1;
            next;
        }
    }
    return @vars;
}

使用以下代码进行测试:

my @variables = extractVars('$a $a{b} $a[c] $scalar @list %hash $list[0][1] $list[-1] $hash{foo}{bar} $aref->{foo} $href->{foo}->{bar} @$aref %$hash_ref %{$aref->{foo}} $hash{\'foo\'} "$a" "$var{abc}"');

如果变量名称包含空格,则不起作用,例如:

  • $hash{"baz qux"}
  • ${ $var->{foo} }[0]