in reply to Parse Loops with flat text files. (code)

A couple of points. First of all, your return logic seems off in your two test subs. Hazarding a guess, I'd say you just wrapped the foreach loops around your previous version that dealt with only one pattern -- but now a line must match *all* the patterns to succeed (it'll return 'undef' if any don't match). I'm thinking you want isbeg() (and isend()) to return true if *any* one of the re's matches the line:

sub isbeg { my $test = shift; foreach (@beginnings) { return 1 if $test =~ /$_/ } return; } sub isend { my $test = shift; foreach (@endings) { return 1 if $test =~ /$_/} return; }

As for your parsing loop, you can use the range operator in scalar context (flip-flop op):

foreach my $line (@lines) { push @extracted, $line if isbeg($line) .. isend($line); last if isend($line); }

You could drop the 'last' statement if the data might have more than one valid section you want to grab.

Also, a style note about your use of 'return undef' -- to return a generic false value just use 'return' with no arguments: it'll return undef in scalar context and an empty list in list context. Thus, not only it is shorter to type, it is more versatile as well.

Replies are listed 'Best First'.
Re:(2) Parse Loops with flat text files. (code)
by deprecated (Priest) on May 13, 2001 at 23:51 UTC
    Hm, I knew of the flip-flop operator but I havent ever used it. Time to go read perlop.

    with regards to returning undef. I use it just as a rule of thumb because it will evaluate to false. However, in subs where I am returning the value of the tested object, I want to be able to return 0 if the test is good -- so I always check to see if defined test( $foo ). dig?

    brother dep.

    --
    Laziness, Impatience, Hubris, and Generosity.

      My only point was regarding when you simply want to return a false value to indicate a subroutine failure. Consider the following contrived example where we only want to process strings beginning with a particular pattern:

      #!/usr/bin/perl -w use strict; my @patterns = (qr/^foo/, qr/^qux/); my @strings = ('foo bar', 'bar bar', 'qux bar'); my @stuff; foreach my $string (@strings){ if(@stuff = dice_it($string)){ print "Processing: $string\n"; process_stuff(@stuff); } } sub dice_it { my $string = shift; foreach my $pat (@patterns) { return split //, $string if $string =~ /$pat/; } return undef; } sub process_stuff { foreach (@_) { print "<$_>"; } print "\n"; }

      I'm not suggesting this a terribly common problem (or that the above is a good way to approach this particular example). I just wanted to point out that returning 'undef' as a failure mode isn't always appropriate -- and people who do so may forget that an array containing one undefined element still evaluates to true so they may bang their head for a while before they realize why they are processing the string 'bar bar' and getting a warning. Changing the last line of dice_it() to just a bare 'return' statement alleviates the problem because it returns the 'right' thing depending on context.

      I was also thinking the flip-flop operator would be good for this. It's what I always try and use for this kind of "in the middle" test.