http://www.perlmonks.org?node_id=733778


in reply to Pattern Matching - a Tricky one

A solution using seek may be better, but I came up with this for finding the customer2 data:

#!/usr/local/bin/perl use strict; use warnings; while ( <DATA> ) { next if ($_ !~ /bakjob(\d)_details/); print "bakjob$1:\n"; my $found = 0; while ($found < 2) { my $line = <DATA>; if ($line =~ /customer2/) { $found++; my @customer2_data = split(/=/, $line); print "$found- $customer2_data[1]"; } } } END; __DATA__ bakjob1_details = { credit = { customer1= 2000.0, customer2 = -1500.0 customer3 = 0.0, }, debit = { customer1= 50000.0, customer2 = -2000.0, customer3 = 0.0, } }, bakjob2_details = { credit = { customer1= 1000.0, customer2 = 200.0, customer3 = 500.0, }, debit = { customer1= 600.0, customer2 = 659.0, customer3 = 887.0, } }

Prints:

% testing.pl bakjob1: 1- -1500.0 2- -2000.0, bakjob2: 1- 200.0, 2- 659.0,

Replies are listed 'Best First'.
Re^2: Pattern Matching - a Tricky one
by linuxer (Curate) on Jan 02, 2009 at 15:55 UTC
    my $found = 0; while ($found < 2) { my $line = <DATA>; if ($line =~ /customer2/) { $found++; my @customer2_data = split(/=/, $line); print "$found- $customer2_data[1]"; } }

    Don't you run into a infinite loop with this? In case $found is less than 2 and <DATA> has reached its end-of-file, there will be no more matches and $found won't be incremented... So it will loop quite a while ;o))

    So, maybe this would be better:

    my $found = 0; while ( $found < 2 and my $line = <DATA> ) { if ( $line =~ m/customer2/ ) { # ... } }

    Even if this case only appears, if the input data is corrupt, I would try to avoid such construct.

      Ah, good call on the infinite loop. Sometimes I forget that you can't trust your input.

      There's a bit more I could have done with this, such as detecting/capturing whether I was in a credit or a debit section, as that would presumably be good to know. But, this has the basics at least.