在找到第一场比赛后退出

时间:2013-11-08 09:29:51

标签: perl

我需要在找到第一个匹配后退出循环并转到循环中的另一个搜索

use strict;
use warnings;

my %iptv;
sub trim($) {
    my $string = shift;
    $string =~ s/\r\n//g;   
    $string =~ s/^\s+//;    
    $string =~ s/\s+$//;    
    return $string;

my @files=</tests/*>;
open IN, "/20131105.csv";
LINE: while (<IN>) {
        chomp;
         my @result = split(/;/,$_);
         my $result1 = trim($_);
         $result[1] = trim($result[1]);
         $iptv{$result[1]} = $result1;
    }
close IN;

foreach my $file (@files) {
        open FILE, "$file";
        while (<FILE>) {
                chomp;
                my ($mac, $date) = split(/;/,$_);               
                my @date1 = split(/\s/, $date);
                print "$iptv{$mac};$date1[0]\n" if defined $iptv{$mac};
                last LINE if (defined $iptv{$mac});
                }
close FILE;
}

我尝试使用“最后”功能,但它找到第一个匹配并结束程序。我必须放在哪里?

2 个答案:

答案 0 :(得分:1)

让我们看一下文档:

$ perldoc -f last
last LABEL
last    The "last" command is like the "break" statement in C (as used
        in loops); it immediately exits the loop in question. If the
        LABEL is omitted, the command refers to the innermost enclosing
        loop. The "continue" block, if any, is not executed:

            LINE: while (<STDIN>) {
                last LINE if /^$/;  # exit when done with header
                #...
            }

        "last" cannot be used to exit a block that returns a value such
        as "eval {}", "sub {}" or "do {}", and should not be used to
        exit a grep() or map() operation.

        Note that a block by itself is semantically identical to a loop
        that executes once. Thus "last" can be used to effect an early
        exit out of such a block.

        See also "continue" for an illustration of how "last", "next",
        and "redo" work.

我们可以在这里清楚地了解如何使用last。如果省略标签,则会突破最里面的循环。因此,只有在我们不希望这样做的情况下,我们才会使用标签。你想要这个,所以你不需要标签。

关于您的代码的一些注意事项:

检查open的返回值,并使用三个带有词法文件句柄的参数。

open my $fh, "<", $file or die "Cannot open $file: $!";

这也有一个好处,当词法变量$fh超出范围时,文件句柄将被关闭。

当您在\s上拆分时,您会拆分一个空格。大多数情况下,这不是你想要的。例如,如果你有一个日期,如

$str = "Jan  1 2013"    # (note the two consecutive spaces)

...这将分成列表"Jan", "", "1", "2013"(注意空字段)。如果空字段是相关的,例如使用类似csv的数据,这只是你想要的。 split的默认行为使用' '(空格字符),其行为类似/\s+/,但它也会删除前导空格。

请注意,此循环中的最后两个语句可以合并。此外,不需要使用临时数组@date1。所以你的代码看起来像:

open my $fh, "<", $file or die "Cannot open $file: $!";
while (<$fh>) {
    chomp;
    my ($mac, $date) = split /;/, $_;
    ($date) = split ' ', $date;
    if (defined $iptv{$mac}) {
        print "$iptv{$mac};$date\n" ;
        last;
    }
}

答案 1 :(得分:0)

foreach my $file (@files) {
    open FILE, "$file";
    LINE: while (<FILE>) {
            chomp;
            my ($mac, $date) = split(/;/,$_);               
            my @date1 = split(/\s/, $date);
            print "$iptv{$mac};$date1[0]\n" if defined $iptv{$mac};
            last LINE if (defined $iptv{$mac});
            }
close FILE;
}

应该确保你只退出内循环。 我想如果你完全摆脱last背后的LINE标签,它也可以正常工作,但我建议总是使用带有last的标签,以确保它没有做出意想不到的事情。如果你添加了一个额外的内部循环而忘记了last,你希望在外面留一个更远的循环。