Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Matching next line in text file

by YYCseismic (Beadle)
on Jul 03, 2008 at 17:18 UTC ( [id://695395]=perlquestion: print w/replies, xml ) Need Help??

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

Greetings, fellow Monks.

I need help with yet another problem. I want to test the next line in a file to see if it is a certain type, or a new data set, or the end of file. Any idea how I can do this? Here's what I have so far:

open(IN, '<', $file) or die "Couldn't open $file for reading: $!\n\n"; my (@hdr, %stn, %seg); my ($lname); while (<IN>) { if (/^H/ ... /[<\[]/) ## If it's a header line... { push(@hdr, $_); ## ...add it to @hdr next; } next if (/reclin/i); ## If it's a DISCO header, ignore; continue to ## next iteration ## Not a header, so must be data.... ( $lname = substr($_,1,16) ) =~ s/\s+//g; ( my $s = substr($_,17,8) ) =~ s/\s+//g; ( my $x = substr($_,45,8) ) =~ s/\s+//g; ( my $y = substr($_,53,8) ) =~ s/\s+//g; ( my $z = substr($_,61,5) ) =~ s/\s+//g; $stn{$s} = [ $x, $y, $z ]; ## HoA: Keys = Stn ID ## Value = Stn Coords

This builds an HoA of station numbers and coordinates. After this point, I want to check if the next line is a header line (/^H/ or /reclin/) or data from another seismic line. (The first header line always starts with 'H'.) If it is any of those, I want to "save" the current %stn hash and @hdr array to a hash as follows:

$seg{$lname} = { 'header' => \@hdr, 'stations' => \%stn, };

(I think I've done the references correctly.) Then I need to clear the @hdr array and %stn hash to get ready for the next set of data. Data samples follow.

Data Sample, Case 1:

__DATA__ 80-101 412 54175659N114551423W 635314260187896 6756 80-101 413 54175657N114551794W 635247260187870 6760 80-101 414 54175655N114552165W 635180260187843 6775 80-101 415 54175653N114552535W 635113360187817 6748 80-101 416 54175650N114552905W 635046560187790 6721 H CLIENT : ************* H PROSPECT : ************* H CONTRACTOR : CANJAY EXPLORATION LINE NAME : 80-103 H SURVEY CO. : CANJAY EXP. UNIQUE ID : *******

Data Sample, Case 2:

__DATA__ 80-101 412 54175659N114551423W 635314260187896 6756 80-101 413 54175657N114551794W 635247260187870 6760 80-101 414 54175655N114552165W 635180260187843 6775 80-101 415 54175653N114552535W 635113360187817 6748 80-101 416 54175650N114552905W 635046560187790 6721 80-103 224 54160602N114433190W 648117760157647 6774 80-103 225 54160602N114433561W 648050760157627 6769 80-103 226 54160602N114433931W 647983760157606 6763 80-103 227 54160602N114434302W 647916760157585 6758 80-103 228 54160603N114434672W 647849760157564 6753

Replies are listed 'Best First'.
Re: Matching next line in text file
by moritz (Cardinal) on Jul 03, 2008 at 17:27 UTC
    I want to test the next line in a file to see if it is a certain type, or a new data set, or the end of file. Any idea how I can do this?
    my $current = <$handle>; while (my $next = <$handle>){ # your loop here $current = $next; }

    In the loop body have the current and the next line available.

      I'm not sure I see where to put this chunk of code. I'm thinking that your my $current = <$handle>; and while statement would replace my while (<IN>), but I'm not certain. If so, then I (think I) understand what's going on. Otherwise I'm totally confused. Can you please elaborate?

Re: Matching next line in text file
by pc88mxer (Vicar) on Jul 03, 2008 at 17:49 UTC
    The variable $stn is the current hash you are building up. When you encounter a /^H/ or /^reclin/ or the end of input, you want to save that hash to your array and reset it:
    my $stn; # current stn hash being constructed ... while (<IN>) { if (/^H/ || /^reclin/i) { if ($stn) { ...save $stn...; $stn = undef; # reset stn hash } } if (/^H/ ... /[<\[]/) { ... same code ... } next if (/^reclin/i); ... parse new $stn hash values ... $stn->{$s} = [ $x, $y, $z ]; } if ($stn) { ...save $stn... }

      I don't know if that's quite what I want.

      I'm building a couple of hashes on the fly here. One of them holds station ID as keys and arrays of station coordinates as values. This I've called %stn. When I reach the next SEG-P1 header block, I want to save this %stn hash into another hash that I've called %seg (see code sample in original question).

      But I also want to be able to save this when there is no header block between data sets. An example of this is the data sample of Case 2 above.

      After all this saving is done (I also need to put the header array @hdr into the %seg hash), I want to empty the station hash (%stn) and the header array so that they can accept the next data set.

      Also, I tried the $stn->{$s} syntax, and it didn't work. I got the error that $stn wasn't part of a package (I hadn't declared it lexically -- rather, I had declared it lexically as a hash, not a scalar, variable).

        I made $stn a hash ref because this isn't going to work:

        $seg{$lname} = { 'header' => \@hdr, 'stations' => \%stn, };
        You'll find that the header will always point to the same array. The same will be true for stations - all of them will be the same hash.

        However, if you make the stn hash a hash ref, then this will work:

        # time to save stn and headers: $seg{$lname} = { header => [ @hdr ], stations => $stn }; @hdr = () $stn = undef;
        Note the square brackets around @hdr - this will create a new array.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://695395]
Approved by kyle
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (7)
As of 2024-03-28 21:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found