in reply to Re^3: Loop problem: jumps one record
in thread Loop problem: jumps one record

Hi Hauke, This is an example of the file format:
blocked using dummy1 (total: 6) 3 rzxwrvxk.com 1 correio.biz 1 facebook.com 1 213.183.58.6 blocked using dummy2 (total: 330) 2 118.125.110.201 1 61.2.46.20 blocked using dummy3 (total: 5) 2 hinet.net 1 219.140.15.195 1 219.139.16.134 1 222.189.112.23 blocked using dummy4 (total: 53) 5 66.23.212.67 5 66.23.212.70 4 66.23.212.68 4 66.23.212.69 Relay access denied (total: 13) 1 46.183.217.174 1 46.183.220.137 1 46.183.220.138
Code:
use strict; use warnings; my $ip=""; my $io; while (<>) { if (/blocked.using/) { do { $io = <>; $ip = $2 if $io =~ /(\d+)\s+(\S+)/; print $ip; #adding to database; } until ($io !~ /(\d+)\s+(\S+)/); } if (/Relay.access.denied/) { do { $io = <>; $ip = $2 if $io =~ /(\d+)\s+(\S+)/; print $ip; # adding to database; } until ($io !~ /(\d+)\s+(\S+)/); } }
Output I get :
rzxwrvxk.com correio.biz facebook.com 213.183.58.6 213.183.58.6 hinet.net 219.140.15.195 219.139.16.134 222.189.112.23 222.189.112.23 46.183.217.174 46.183.220.137 46.183.220.138

Replies are listed 'Best First'.
Re^5: Loop problem: jumps one record
by haukex (Archbishop) on Jan 31, 2017 at 13:13 UTC

    Hi math&ing001,

    When I run your code against your sample input, it does not match the output you gave; also you didn't say what output you expect - the more precise you are in your questions, the better we are able to help :-)

    What I see happening is that I get stuff like "(total:" in the output, the reason is that the regex /(\d+)\s+(\S+)/ also matches the string "blocked using dummy3 (total: 5)". One way to avoid this would be to be more specific in your regexes. One simple fix would be to write your regexes as /^\s*(\d+)\s+(\S+)\s*$/.

    Anyway, the first thing I would suggest is that you don't use do { } until () loops, and instead use while loops, and then use the last command to break out of the loop under certain conditions, this will give you more precise control. For example, the first of your inner loops could be written like this:

    if (/blocked.using/) { while (<>) { /^\s*(\d+)\s+(\S+)\s*$/ or last; $ip = $2; print "$ip\n"; } }

    As for the state machine approach:

    use warnings; use strict; use constant { IDLE => 0, RELAY => 1, BLOCKED => 2, }; my $state = IDLE; while (<>) { chomp; if (/Relay.access.denied/) { $state = RELAY; } elsif (/blocked.using/) { $state = BLOCKED; } elsif (/^\s*(\d+)\s+(\S+)\s*$/) { if ($state == RELAY) { print "Relay Access Denied: $2\n" } elsif ($state == BLOCKED) { print "Blocked: $2\n" } } else { $state = IDLE; } }

    Hope this helps,
    -- Hauke D

Re^5: Loop problem: jumps one record
by tybalt89 (Monsignor) on Jan 31, 2017 at 18:24 UTC

    Just use the section name as the state flag...

    #!/usr/bin/perl # http://perlmonks.org/?node_id=1180665 use strict; use warnings; my $section = ''; while(<DATA>) { if( /(.*)\(total: \d+\)/ ) # get section name { $section = $1; } elsif( $section =~ /Relay access denied/ and /^\s*\d+\s+(\S+)\s*$/ ) { print "$section $1\n"; # add $1 to DB one way } elsif( $section =~ /blocked using/ and /^\s*\d+\s+(\S+)\s*$/ ) { print "$section $1\n"; # add $1 to DB a different way } } __DATA__ Relay access denied (total: 13) 1 46.183.217.174 1 46.183.220.137 1 46.183.220.138 1 46.183.220.139 1 46.183.223.239 1 218.38.243.204 1 185.29.8.198 1 185.29.9.133 1 185.29.9.135 1 46.183.217.162 1 46.183.217.165 1 46.183.217.169 1 91.236.75.169 Sender address rejected: Access denied (total: 50) 1 77.236.75.169 blocked using dummy1 (total: 6) 3 rzxwrvxk.com 1 correio.biz 1 facebook.com 1 213.183.58.6 blocked using dummy2 (total: 330) 2 118.125.110.201 1 61.2.46.20 blocked using dummy3 (total: 5) 2 hinet.net 1 219.140.15.195 1 219.139.16.134 1 222.189.112.23 blocked using dummy4 (total: 53) 5 66.23.212.67 5 66.23.212.70 4 66.23.212.68 4 66.23.212.69 Relay access denied (total: 13) 1 46.183.217.174 1 46.183.220.137 1 46.183.220.138
Re^5: Loop problem: jumps one record
by poj (Abbot) on Jan 31, 2017 at 13:03 UTC

    What is difference between the 2 #adding to database sections, are they updating different tables ?

    poj
      poj,
      same table but with different criteria.

        Ok, since you didn't detail the criteria you need to adapt this as required

        #!perl use warnings; use strict; my $criteria; while (<>) { next unless /\S/; # skip blank lines if (/(Relay access denied|blocked using)/){ $criteria = $1; next; } if (/\d+\s+(\S+)/ && defined $criteria){ print "update db $criteria = $1\n"; } else { $criteria = undef; } }
        poj