user2075811
user2075811

Reputation: 17

exit while loop after find first match

I need to exit the loop after find first match and go to another search in the loop

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

I tried to use "last" function but it finds first match and ends program. where I have to put last?

Upvotes: 0

Views: 4938

Answers (2)

TLP
TLP

Reputation: 67900

Lets take a look at the documentation:

$ 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.

We can clearly read here about how to use last. If a label is omitted, it breaks out of the innermost loop. So only in the case where we do not want this do we use a label. You want this, so you do not want a label.

Some notes on your code:

Check the return value of open, and use three arguments with a lexical file handle.

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

This also has the benefit that when the lexical variable $fh goes out of scope, the file handle is closed.

When you split on \s you split on a single whitespace. Most often, this is not what you want. If you for example have a date such as

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

...this will split into the list "Jan", "", "1", "2013" (note the empty field). This is only what you want if empty fields are relevant, such as with csv-like data. The default behaviour of split uses ' ' (a space character), which acts like /\s+/, except that it also strips leading whitespace.

Note that the two last statements inside this loop can be merged. Also, the use of the temp array @date1 is not needed. So that your code looks like:

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

Upvotes: 1

DeVadder
DeVadder

Reputation: 1404

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

Should make sure that you only exit the inner loop. I suppose it would work just as well if you got rid of the LINE Label right behind the last alltogether but i would suggest allways using a label with last to be certain that it does not do something unexpected in case you add an additional inner loop and forget about the last within that you expect to leave a loop farther on the outside.

Upvotes: 0

Related Questions