in reply to Loop problem: jumps one record
Hi Anonymous,
The problem is that every time you write <>, a new record is read from the file. while (<>) { ... } will assign the current record to the $_ variable, so inside the loop you should just use that instead of <>. Note that when you write a regex without the =~ operator, it will implicitly be tested against the $_ variable.
One way to do this is a state machine type approach, this has the advantages that you only read from <> once, it has no nested loops, and it's very extensible.
use warnings; use strict; use constant { IDLE => 0, IP_ADDRS => 1, }; my $state = IDLE; while (<>) { if ($state == IDLE) { if (/Relay.access.denied/) { $state = IP_ADDRS } } elsif ($state == IP_ADDRS) { if (/(\d+)\s+(\S+)/) { print "$2\n" } else { $state = IDLE } } }
Of course, the nested loops approach is much shorter in this case, I just personally wouldn't do this because if your code gets longer, it will get more complicated and much harder to maintain than the above approach.
use warnings; use strict; while (<>) { if (/Relay.access.denied/) { while (<>) { /(\d+)\s+(\S+)/ or last; print "$2\n"; } } }
Update: For completeness, note that it's also possible to invert the structure of the conditions in the state machine approach, which allows for a bit more error checking. Or, if you don't care about those conditions, they can be removed from the following code to make it shorter (about as long as the above state machine code). You can choose whether you want to use the above approach or the following one based on which one makes your logic easier to express. In this case it's roughly equivalent, but if your code gets longer that might change.
use warnings; use strict; use constant { IDLE => 0, IP_ADDRS => 1, }; my $state = IDLE; while (<>) { chomp; if (/Relay.access.denied/) { if ($state == IDLE) { $state = IP_ADDRS } elsif ($state == IP_ADDRS) { warn "unexpected: $_" } } elsif (/(\d+)\s+(\S+)/) { if ($state == IDLE) { warn "unexpected: $_" } elsif ($state == IP_ADDRS) { print "$2\n" } } else { if ($state == IDLE) { } elsif ($state == IP_ADDRS) { $state = IDLE } } }
Hope this helps,
-- Hauke D
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: Loop problem: jumps one record (updated)
by math&ing001 (Novice) on Jan 31, 2017 at 11:59 UTC | |
by Discipulus (Canon) on Jan 31, 2017 at 12:39 UTC | |
by haukex (Archbishop) on Jan 31, 2017 at 12:26 UTC | |
by math&ing001 (Novice) on Jan 31, 2017 at 12:54 UTC | |
by haukex (Archbishop) on Jan 31, 2017 at 13:13 UTC | |
by tybalt89 (Monsignor) on Jan 31, 2017 at 18:24 UTC | |
by poj (Abbot) on Jan 31, 2017 at 13:03 UTC | |
by math&ing001 (Novice) on Jan 31, 2017 at 13:09 UTC | |
|