断开循环会导致不同的结果

时间:2015-04-01 19:56:05

标签: regex perl

我有这段代码:

#!/usr/bin/perl
use strict;
use warnings;

my $judge_exes = {
    "^A" => "foo",
    "^B" => "bar",
    "^C" => "baz",
};

sub get_judge {
    my ($test_id) = @_;
    my $exe = undef;
    while (my ($regex, $judge) = each %$judge_exes) {
        if ($test_id =~ /$regex/) {
            $exe = $judge;
            last;
        }
    }

    if ($exe) {
        return $exe;
    } else {
        return "Undefined!";
    }
}

print get_judge("A1");
print get_judge("B2");
print get_judge("C3");

(ideone:http://ideone.com/slxebG

我希望获得输出foobarbaz,但最终得到fooUndefined!baz。但是,当我注释掉last语句时,我得到了正确的行为:

#!/usr/bin/perl
use strict;
use warnings;

my $judge_exes = {
    "^A" => "foo",
    "^B" => "bar",
    "^C" => "baz",
};

sub get_judge {
    my ($test_id) = @_;
    my $exe = undef;
    while (my ($regex, $judge) = each %$judge_exes) {
        if ($test_id =~ /$regex/) {
            $exe = $judge;
            # last;
        }
    }

    if ($exe) {
        return $exe;
    } else {
        return "Undefined!";
    }
}

print get_judge("A1");
print get_judge("B2");
print get_judge("C3");

(ideone:http://ideone.com/QJpxbK

为什么会这样? (我使用的是Perl 5.16.2,但问题也存在于5.10.1以及无论是谁使用的。)

  • 据我了解,last只是突破while循环,这就是我想要的。
  • $exe似乎不是一个替代的假值,导致我遇到错误的if-branch。 (我可以提早回来,这会更好,但我仍然不明白这个原因。)
  • 我认为我正确地取消引用哈希引用。
  • 我认为正则表达式匹配不会产生与循环终止相关的任何副作用。
  • 正则表达式似乎正确匹配,因为在某些情况下我实际上可以让它们匹配得恰当,所以我认为这不是插值问题。
  • 我没有修改我正在迭代的容器。

我只是犯了一些愚蠢的非Perl相关错误吗?

2 个答案:

答案 0 :(得分:1)

你变得困惑。我不确定混淆在哪里,但你必须知道each运算符在调用之间保持其状态。这意味着last循环内的while将不会终止迭代。相反,它将在下一次遇到它时继续停留的地方。

你也应该保留双引号,因为它们插入任何标量或数组变量或反斜杠控制字符。

以下是我建议你编写算法的方法

#!/usr/bin/perl
use strict;
use warnings;
use 5.010;

my $judge_exes = {
    '^A' => 'foo',
    '^B' => 'bar',
    '^C' => 'baz',
};

say get_judge('A1', $judge_exes);
say get_judge('B2', $judge_exes);
say get_judge('C3', $judge_exes);
say get_judge('D4', $judge_exes);
say get_judge('E5', $judge_exes);

sub get_judge {
    my ($test_id, $judges) = @_;

    for my $re ( keys %$judges ) {
        return 1 if $test_id =~ /$re/;
    }

    'Undefined!';
}

<强>输出

1
1
1
Undefined!
Undefined!

答案 1 :(得分:0)

哦,看起来行为是explained here

  

在标量上下文中使用keys %hash返回散列中的键数,并重置与散列关联的迭代器。如果使用last提前退出循环,则可能需要执行此操作,以便在重新输入时,哈希迭代器已重置。

没想到 - 我以为each会重置迭代器。