Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Re: Need advice on how to break foreach parsing loop into functions

by Anno (Deacon)
on Sep 15, 2007 at 15:21 UTC ( #639177=note: print w/replies, xml ) Need Help??


in reply to Need advice on how to break foreach parsing loop into functions

Your code has a bug. In the regex in "if ($line =~ m/^interface (\.*)/) {" you have escaped the dot, which isn't what you want. The regex should be "/^interface (.*)/)".

Less importantly, you are using a leading ampersand in the sub calls "&parse_ethernet($1);" and "&parse_gigabit($1);". They are unnecessary and you shouldn't use them unless you know what they do and want tthe effect. Here, you don't.

As for your parsing problem, you can set the input separator to "!\n" when you read the file. Then you will have one complete chunk of input to give to any of the subs parse_* or whatever. Note that these must now expect a multiline string containing all the information in the current chunk.

Here is a sketch:

$/ = "!\n"; while ( <DATA> ) { chomp; if ( /^interface (.*)/ ) { if ( $1 eq 'Ethernet' ) { parse_ethernet( $_); } elsif ( $1 eq 'Gigabit' ) { parse_gigabit( $_); } } elsif ( /^system (.*)/ ) { # blah... } } sub parse_gigabit { my $chunk = shift; $chunk =~ tr/\n/ /; print "GIGABIT: $chunk\n"; } sub parse_ethernet { my $chunk = shift; $chunk =~ tr/\n/ /; print "ETHERNET: $chunk\n"; } __DATA__ ! interface Ethernet blah... blah... ! interface Gigabit blah... blah... ! interface Ethernet blah... !
Anno

Replies are listed 'Best First'.
Re^2: Need advice on how to break foreach parsing loop into functions
by Prof Vince (Friar) on Sep 16, 2007 at 08:36 UTC
    For expanding Anno's solution, you can use a dispatch table to apply the corresponding policy :
    my %parsers = ( 'Ethernet' => sub { my $chunk = shift; $chunk =~ tr/\n/ /; return "ETHERNET: $chunk"; }, 'Gigabit' => sub { my $chunk = shift; $chunk =~ tr/\n/ /; return "GIGABIT: $chunk"; } ); $/ = "!\n"; $\ = "\n"; while ( <DATA> ) { chomp; if ( /^interface (.*)/ && $1 && exists $parsers{$1} ) { print $parsers{$1}( $_ ); } elsif ( /^system (.*)/ ) { # blah... } }
    Edit: As anonymous said, ( ) instead of { }. Copypasta from/to Firefox is treacherous.
      the statement

      my %parsers = { ... };

      seems wrong. should it not be

      my %parsers = ( ... );

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://639177]
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (2)
As of 2018-07-19 00:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    It has been suggested to rename Perl 6 in order to boost its marketing potential. Which name would you prefer?















    Results (398 votes). Check out past polls.

    Notices?