Reputation: 17
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
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
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