SPUG: multiline matching question

John W. Krahn krahnj at telus.net
Thu Sep 8 19:18:51 PDT 2005

Richard Wood wrote:
> SPUGsters, 
> I am trying to efficiently grab sets of data from
> multiple lines of a file and print the collected data
> out on one line per set.  I've never tried multi line
> matching before ( I usually just write a program that
> tests which kind of line I am processing).  But I
> believe that this can be done in one match statement. 
> So I would like some help.  Currently, in the test
> file that I am including, I am getting the data from
> the second set of lines which seems pretty unusual to
> me.  I'm looking forward to understanding what I am
> doing wrong.
> The file consists of 150 character records.  Every
> third record starts a new set of data.  I need bits
> and pieces from records 1 & 2 of each set.  
> here is the command line that I am using:
> $ perl -wne 'undef
> $/;/(AP01).{5}(..)..(\d\d\d).{38}(.{19}).{9}(.{5}).{64}(.{80})/gs
> and print "$1 $2 $3 $4 $5 $6\n";' sample.txt   

$ perl -MO=Deparse -wne 'undef
and print "$1 $2 $3 $4 $5 $6\n";' sample.txt
BEGIN { $^W = 1; }
LINE: while (defined($_ = <ARGV>)) {
    undef $/;
    print "$1 $2 $3 $4 $5 $6\n" if
-e syntax OK

You are undefining the input record separator after the program has read the
first line so you need to either undefine it in a BEGIN block or with a
command line switch:

perl -ne'BEGIN{undef $/}...'


perl -0777ne'...'

Your expression '//gs and print ""' will only execute once.  You need to loop
over each match like:

perl -0777ne'print "$1 $2 $3 $4 $5 $6\n" while
/^(AP01).{5}(..)..(\d\d\d).{38}(.{19}).{9}(.{5}).{64}(.{80})/gms' sample.txt

Another way to do it:

perl -F'\n\s+\n' -0777ane'/^AP01/ and print join " ", unpack(
"a4x5a2x2a3x38a19x9a5x64a80", $_ ), "\n" for @F' sample.txt

use Perl;

More information about the spug-list mailing list