in reply to Re^2: Loop problem: jumps one record (updated)
in thread Loop problem: jumps one record

Hi math&ing001,

I also run into another problem : the loop skips the second round of entries as there are a bunch of "/Relay.access.denied/" in the file. ... So my question is, is there a way to tell <> to go back one line at the end of the loop.

There isn't a good way to do that, however, in the code examples I showed, it is of course possible to do multiple things on each line of input, which is how I would approach the solution. However, it's hard for me to fully understand the problems you described, it would be helpful if you could provide more short sample input that illustrates the problem along with the output you are expecting for that sample input. See also Short, Self-Contained, Correct Example and How do I post a question effectively?

Regards,
-- Hauke D

Replies are listed 'Best First'.
Re^4: Loop problem: jumps one record
by math&ing001 (Novice) on Jan 31, 2017 at 12:54 UTC
    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

      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

      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

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

      poj
        poj,
        same table but with different criteria.