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

Hello! I have an output text file looking like this:

...
GRAZ X 4
Y 6
Z 3
N 22
E 3
U 15

KIGB X 2
Y 6
Z 6
N 13
E 20
U 11

...

I need to extract for each station (in this case GRAZ and KIGB) the N,E,U and sort it something like this:
station N E U
GRAZ 22 3 15
KIGB 13 20 11

How do I tell perl to find station and then from that station goes to next line with "N" and takes numbers at xth position, and then goes to line where it is "E", ..and so on.

Sorry if it is too stupid, I am just not experienced in perl and dont know if there is some simple way to do it? I have quite large files and lots of stations to extract, so I want to avoid manual approach.

Thank you!

Replies are listed 'Best First'.
Re: Extract data from next n-th line
by Fletch (Bishop) on Jun 02, 2010 at 18:09 UTC
    • Read the file line by line
    • If the line is a station identifier, save it off into (say) $state{ 'station' }
    • Likewise store off $state{ 'N' } for the other lines as they're encountered
    • When you find the end of a record (presumably by hitting a blank line), print the current %state and clear it.
    • Lather, rinse, repeat.

    Alternately if your records are delimited by blank lines you could diddle $/ and process the whole record at a time.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Re: Extract data from next n-th line
by toolic (Bishop) on Jun 02, 2010 at 18:15 UTC
    This should get you started:
    use strict; use warnings; my $station; my %params; while (<DATA>) { if (/^(\w{2,})/) { $station = $1; } elsif (/^(\w)\s+(\d+)/) { $params{$1} = $2; } else { print "$station @params{qw(N E U)}\n"; } } __DATA__ GRAZ X 4 Y 6 Z 3 N 22 E 3 U 15 KIGB X 2 Y 6 Z 6 N 13 E 20 U 11
Re: Extract data from next n-th line
by ikegami (Patriarch) on Jun 02, 2010 at 20:09 UTC
    If there's a blank line between the records as you showed, you can use "paragraph mode" (local $/ = "";).
    local $/ = ""; while (<>) { my ($station, %fields) = /(\S+)/g; print(join(' ', $station, @fields{qw( N E U )}), "\n"); }

    Or if the values can contain whitepace,

    local $/ = ""; while (<>) { my $station = s/^(\S+)\s+// ? $1 : undef; my %fields = /(\S+)\s+([^\n]*)\n/g; print(join(' ', $station, @fields{qw( N E U )}), "\n"); }
Re: Extract data from next n-th line
by jwkrahn (Abbot) on Jun 02, 2010 at 18:45 UTC
    $ echo "GRAZ X 4 Y 6 Z 3 N 22 E 3 U 15 KIGB X 2 Y 6 Z 6 N 13 E 20 U 11 " | perl -e' $/ = ""; $\ = "\n"; print "station N E U"; while ( <> ) { + print join " ", /\A(\S+)(?=.*^N\s+(\d+))(?=.*^E\s+(\d+))(?=.*^U\s+ +(\d+))/sm; } ' station N E U GRAZ 22 3 15 KIGB 13 20 11
Re: Extract data from next n-th line
by dineed (Scribe) on Jun 03, 2010 at 04:57 UTC

    A little different approach using a two-dimensional array...

    # using two dimensional array # assumes sequence of records is always N...E...U... use strict; use warnings; my @station; my $row = -1; my $col = 0; print "STATION\tN\tE\tU\n"; while (<DATA>) { if ($_ =~ /^(\w\w+)\s+..*$/) { $col = 0; $station[++$row][$col] = $1; } elsif ($_ =~ /^[N|E|U]\s+(\d+)$/) { $station[$row][++$col] = $1; } } for(my $i = 0; $i <= $row; $i++) { for(my $j = 0; $j <= $col; $j++) { if($j > 0) { print "\t"; } print"$station[$i][$j]"; } print "\n"; } __DATA__ GRAZ X 4 Y 6 Z 3 N 22 E 3 U 15 KIGB X 2 Y 6 Z 6 N 13 E 20 U 11

    Output:

    STATION N E U GRAZ 22 3 15 KIGB 13 20 11