Perl:使用?:运算符时出现意外的匹配变量

时间:2011-09-06 03:37:52

标签: regex perl cgi taint-checking

尝试解开Perl中的一些变量,以下代码效果很好:

if ($year =~ /^(\d{4})$/) {
        $year = $1;
} else {
        &invalid("year");
}

在上面的例子中,如果有效,$ 1包含$ year。但是,使用?:运算符时,$ 1在有效时包含“1”:

($year =~ /^(\d{4})$/) ? $year = $1 : &invalid("year");

有人看到我可能有过错吗?我很困惑为什么会这样。它只发生在这台机器上。或者说,我已成功使用了?运算符用于返回多年的正确匹配变量。我还没有在任何其他机器上尝试过这段代码。

This is Perl, v5.8.8 built for x86_64-linux-thread-multi

3 个答案:

答案 0 :(得分:6)

请注意优先顺序。

对比http://codepad.org/vEPnhWfH按预期工作,http://codepad.org/nXVU5CA7没有。当然,我稍微调整了代码以避免调用invalid,但我怀疑这可能是问题的根源。

在这两种情况下,虽然$1包含“2011”,但也许您应该按照mu的第一条评论中的要求显示其他代码。

<强>更新

我更改了键盘示例以使用对&invalid的调用,但错误未显示。

sub invalid {
    print("INVALID\n");
}

sub check_with_if {
    print("Trying with if-statement\n");
    my $year = shift;
    if ($year =~ /^(\d{4})$/) {
        $year = $1;
    } else {
        &invalid($year);
    }
    print("\$1 is $1 and \$year is $year"."\n");
}

sub check_with_conditional {
    print("Trying with conditional expression\n");
    my $year = shift;
    ($year =~ /^(\d{4})$/) ? $year = $1 : &invalid($year);
    print("\$1 is $1 and \$year is $year"."\n");
}

check_with_if("2011");
check_with_conditional("2011");

输出

Trying with if-statement 
$1 is 2011 and $year is 2011
Trying with conditional expression
$1 is 2011 and $year is 2011

http://codepad.org/z22GMEcn

编辑2 也适用于Mac上的5.12.3。

我同意Jonathan的说法,你可能在5.8.8中发现了一个已修复的错误。如果您非常好奇,可以通过Perl更改,例如:

答案 1 :(得分:5)

Damien Conway的Perl最佳实践解释了使用匹配变量$1等等的一些缺陷,其中之一就是:

  • 如果正则表达式与任何内容都不匹配,$1不会变为undef,但会保留其先前的值(当然,在大多数情况下,这是不合格的)

我的直觉告诉我你的上下文有问题 - 你的表达式可能会在标量上下文中进行评估,从而在有效时返回匹配数。

所以,我会尝试重写代码,如:

($year) = ( $year =~ /^(\d{4})$/) or &invalid("year");

答案 2 :(得分:3)

使用Perl 5.14.1(在MacOS X 10.7.1上),这个脚本似乎运行正常:

use strict;
use warnings;

my $year = "1984";

sub invalid
{
    my($year) = @_;
    print "Invalid year $year\n";
}

if ($year =~ /^(\d{4})$/)
{
    $year = $1;
}
else
{
    &invalid("year");
}


print "Year1: $year\n";

$year = "1984";
($year =~ /^(\d{4})$/) ? $year = $1 : &invalid("year");

print "Year2: $year\n";

它产生:

Year1: 1984
Year2: 1984

如果同一个脚本在Perl 5.8.8中产生不同的答案,那么大概你已经找到了一个已修复的错误并且升级是有序的。如果Perl 5.8.8产生相同的答案(如Perl 5.14.1),那么你还没有表明你的问题,以便我能理解它并重现问题。