0

最初の一致を見つけた後、ループを終了し、ループ内の別の検索に進む必要があります

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

「last」関数を使用しようとしましたが、最初の一致を見つけてプログラムを終了します。最後にどこに置く必要がありますか?

4

2 に答える 2

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し、レキシカル ファイル ハンドルで 3 つの引数を使用します。

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+/、先頭の空白も削除することを除いて、 のように機能します。

このループ内の最後の 2 つのステートメントはマージできることに注意してください。また、一時配列を使用する@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;
    }
}
于 2013-11-08T12:21:41.190 に答える
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;
}

内側のループのみを終了するようにしてください。LINE ラベルを完全に削除しても同様に機能すると思いますが、追加の内部ループを追加して忘れた場合に予期しないことをしないように、last常にラベルを使用することをお勧めします外側にさらにループを残すと予想される内側lastlast

于 2013-11-08T09:40:19.320 に答える