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

发布于 2024-12-03 03:04:38 字数 496 浏览 1 评论 0原文

尝试在 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

Trying to untaint some variables in Perl, and the following code works great:

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

In the above instance, $1 contains $year if valid. However, when using the ?: operator, $1 contains "1" when valid:

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

Anyone see where I might be at fault? I'm confused why this is happening. It's only happening on this machine. Or rather, I have successfully used the ? operator for returning proper match variables for years. I haven't tried this piece of code on any other machine yet.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

柏林苍穹下 2024-12-10 03:04:38

这里要注意优先级。

将按预期工作的 http://codepad.org/vEPnhWfHhttp://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 也适用于 5.12。 3 在 Mac 上。

我同意 Jonathan 的观点,即您可能在 5.8.8 中发现了一个错误,此后该错误已得到修复。如果您非常好奇,可以通过 Perl 更改进行操作,例如:

Be careful about precedence here.

Contrast http://codepad.org/vEPnhWfH which works as expected, with http://codepad.org/nXVU5CA7 which does not. Of course, I tweaked the code a little bit to avoid calling invalid, but I suspect this may be at the root of the problem.

In both cases, though $1 contains "2011", so perhaps you should show additional code, as requested in the first comment by mu.

UPDATE

I changed the codepad examples to use the call to &invalid and the error does not show up.

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");

Output is

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

EDIT 2 Also works on 5.12.3 on the Mac.

I agree with Jonathan that you may have found a bug in 5.8.8 that has been fixed since. If you are incredibly curious you can work your way through the Perl changes, such as:

森林迷了鹿 2024-12-10 03:04:38

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

  • 如果正则表达式不匹配任何内容,则 $1不会变成 undef,但它保留了以前的值(当然,在大多数情况下是 undef)

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

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

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

Damien Conway's Perl Best Practices explains some of the pitfalls of using the match variables $1 and so on, one of them is that:

  • if the regex doesn't match anything, $1 does not become undef, but it preserves its previous value (which of course, in most cases is undef)

My intuition tells me that you have a problem with contexts - your expression might be evaluated in scalar context, thus returning the number of matches when it is valid.

So, I would try rewriting the code like:

($year) = ( $year =~ /^(\d{4})$/) or &invalid("year");
梦里兽 2024-12-10 03:04:38

使用 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),那么您还没有描述您的问题,以便我可以理解它并重现该问题。

With Perl 5.14.1 (on MacOS X 10.7.1), this script seems to work OK:

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";

It produces:

Year1: 1984
Year2: 1984

If the same script produces a different answer in Perl 5.8.8, then presumably you've hit a bug that has been fixed and an upgrade is in order. If Perl 5.8.8 produces the same answer (as Perl 5.14.1), then you have not yet characterized your problem so that I can understand it and reproduce the issue.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文