Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Iterating and pattern matching on input file

by bartrad (Beadle)
on Jul 31, 2018 at 19:33 UTC ( [id://1219595]=perlquestion: print w/replies, xml ) Need Help??

bartrad has asked for the wisdom of the Perl Monks concerning the following question:

Hi all, after some advice. I'm opening a file and reading through it and look for some key values after the "Count:" text, but my next if's don't seem to be working properly (as they're probably not doing what I think they're doing) and instead it seems to be ignoring the next ifs and just picking up every occurrence of "Count:"

The input file

Checks: Running 'show port | match "Up Yes" | count' Count: 23 lines Checks: Running 'show router interface | match "Up " | count' Count: 4 lines

My Code

open( INPUT, "$folder/$file" ) or die("Could not open $file file"); while ( my $line = <INPUT> ) { next if ( $line =~ m/show port/ ); if ( $line =~ m/Count:\s+(\d+)/ ) { $checks{port}{$stage} = $1; } next if ( $line =~ m/show router interface/ ); if ( $line =~ m/Count:\s+(\d+)/ ) { $checks{l3}{$stage} = $1; } }

Printing out $checks{port}{$stage} shows:

23 4

When it should only show 23 for $checks{port}{$stage} and 4 for $checks{l3}{$stage}...

And a Dumper

$VAR1 = { 'card' => { 'post' => '28615', 'pre' => '28615' }, 'l3' => { 'post' => '28615', 'pre' => '28615' }, 'subs' => { 'post' => '2', 'pre' => '2' }, 'bfd' => { 'post' => 0, 'pre' => 0 }, 'binding' => { 'post' => '28615', 'pre' => '28615' }, 'ospf' => { 'post' => '2', 'pre' => '2' }, 'port' => { 'post' => '28615', 'pre' => '28615' }, 'ldp' => { 'post' => '14', 'pre' => '14' } };

Note, there's other occurrences of "Count" it's picking up but I only included two from the data source to keep things short. Any help is greatly appreciated.

Replies are listed 'Best First'.
Re: Iterating and pattern matching on input file
by roboticus (Chancellor) on Jul 31, 2018 at 20:06 UTC

    bartrad:

    Take a look at what the code in your while loop would do for each line of code:

    • Checks: Running 'show port | match "Up    Yes" | count'
      OK, it matches /show port/, so it would skip rest of the body of the while loop.
    • Count: 23 lines
      It doesn't match /show port/, so it goes to the next line in the loop.
      It matches /Count:\s+(\d+)/, so it would add the value to $checks{port}{$stage}
      It doesn't match /show router interface/, so it goes to the next line in the loop.
      It matches /Count:\s+(\d+)/, so it would add place the value to in $checks{l3}{$stage}
      There's nothing else in the loop to do...
    • Checks: Running 'show router interface | match "Up " | count'
      It doesn't match /show port/, so it goes to the next line in the loop.
      It doesn't match /Count:\s+(\d+)/, so it ignores the body of the if statement.
      It matches /show router interface/, so it would skip the rest of the body of the while loop.
    • Count: 4 lines
      It doesn't match /show port/, so it goes to the next line in the loop.
      It matches /Count:\s+(\d+)/, so it would add the value to $checks{port}{$stage}
      It doesn't match /show router interface/, so it goes to the next line in the loop.
      It matches /Count:\s+(\d+)/, so it would add place the value to in $checks{l3}{$stage}
      There's nothing else in the loop to do...

    So it looks like you're expecting 'next' to mean "read the next line" instead of "ignore the rest of the loop".

    I expect you probably want something like:

    while (my $line = <INPUT>) { my item = "UNKNOWN"; if ($line =~ /show port/) { $item = "port"; } if ($line =~ /show router interface/) { $item = "l3"; } if ($line =~ /Count:\s+(\d+)/) { $checks{$item}{$stage} = $1; } }

    Update: Pressed "create" just a bit too soon!

    Update: As AnomalousMonk mentions, it's not adding the count value.

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      It matches /Count:\s+(\d+)/, so it would add the value to ... [emphasis added]

      I agree with your analysis, except I would say "It matches /Count:\s+(\d+)/, so it would assign the value to ... (overwriting the previous value)." (The phrase "add the value to" suggests something like the  += operation (update: but the OPed code does an assign).)


      Give a man a fish:  <%-{-{-{-<

      Thanks for your response. Yeah, that's exactly what I want - "next line", rather than "next". I've updated the code but doesn't seem to be working?

      my $item = "UNKNOWN"; if ( $line =~ m/show port/ ) { $item = + "port"; } if ( $line =~ m/show router interface/ ) { $item = + "l3"; } if ( $line =~ m/Count:\s+(\d+)/ ) { $checks{$item}{$stage} = + $1; }
      $VAR1 = { 'subs' => { 'post' => '2', 'pre' => '2' }, 'bfd' => { 'post' => 0, 'pre' => 0 }, 'ospf' => { 'post' => '2', 'pre' => '2' }, 'UNKNOWN' => { 'post' => '28615', 'pre' => '28615' }, 'ldp' => { 'post' => '14', 'pre' => '14' } };

      Am I missing something?

        bartrad:

        I can't tell what's wrong as you don't show the input data, nor is there enough code to see what's happening.

        From what you're showing me, I'd guess that there's a spelling error in there and the items you're trying to capture are treated as UNKNOWN.

        You might try showing a bit more of your code and/or your test data.

        ...roboticus

        When your only tool is a hammer, all problems look like your thumb.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1219595]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (5)
As of 2024-04-25 06:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found