Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

Matching string, then getting next line

by minixman (Beadle)
on Mar 08, 2006 at 10:32 UTC ( #535132=perlquestion: print w/replies, xml ) Need Help??

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

All if i have a simple loop that runs over each line of the file. like
for( split(/[\r\n]+/, $content) ) { if(($_ =~ m/35=8/)&&($_ =~ m/$tag1/)&&($_ =~ m/$tag2/)){ printf $_; }elsif(($_ =~ m/35=9/)&&($_ =~ m/$tag1/)) { printf $_; } }

Now the above would match the string i am looking for, but the \r\n splits out the end of my strings line, so the message is.
Message dump: 8=1034=DFG55=TEST90=23435=D 19 06/02/23 11:18:33:984 Sent Message

So when the code above runs it prints out.

But what i need is to catch the next line
19 06/02/23 11:18:33:984 Sent Message

Replies are listed 'Best First'.
Re: Matching string, then getting next line
by inman (Curate) on Mar 08, 2006 at 10:39 UTC
    Hi minixman

    It would be worth trying a slightly different approach to the problem. You have mentioned that your content is coming from a file, it would be easier to work with the file itself line by line, look for the match and then do something with the next line. e.g.

    while (<MYFILE>){ chomp; #remove line feed if (/do the match here/) { my $nextLine = <MYFILE>; # do stuff with the next line here. } }

    This reads the content of the file handle, line by line placing each line into the default $_ variable. You can test to see if you have a match and then take another line from the file.

    If you have all of your content in a list then you can substitute the reading of a line from the file with a shift of a line form the list.

      Hi THe problem with that is, that when perl reads my file which was created on windows, it treats the whole file as one line, that is why i had to use FILE::Slurp to split out the lines. So what i need to do is say okay if you match my line, place the value into a variable and then get the next line whatever it is and place that into a variable.
        I guess that you are trying this with a file that has been generated on Windows and then transferred to a UNIX box. You end up with extra ^M chars when you look at the file using vi. Try trimming the surplus whitespace using a regex
        #!/usr/bin/perl -w use strict; while (<MYFILE>){ s/\s+$//; if (/NEXT LINE MARKER/) { my $nextLine = <MYFILE>; $nextLine =~ s/\s+$//; print "$nextLine\n"; # do stuff with the next line here. } }
        > THe problem with that is, that when perl reads my file
        > which was created on windows, it treats the whole file as one line

        that's odd. most MSDOS/Windows files use CR/LF as the end-of-line marker, but it sounds like your file uses just CR...are you sure it's a DOS file and not a Mac file?

        to read MSDOS/Windows text files, you need to set the input record separator to CR/LF rather than newline (actually, this isn't strictly necessary. if you don't do it, you just end up with a CR at the end of each line. chomp will get rid of it)



        to read Mac text files, set it to just CR:


        see the man page for 'perlvar' for more info.

Re: Matching string, then getting next line
by lukeyboy1 (Beadle) on Mar 08, 2006 at 16:46 UTC
    One thing that's good to note is that I'd personally say don't just assume that $_ holds what you think it does. My advice would be NOT to use $_, particularly when using regular expressions.

    My reasoning is that anonymous variables almost always store up a world of trouble for you, and although I haven't looked at your example in any detail, I would think that doing multiple matches MIGHT have the effect of altering $_......

    Don't take this the wrong way, though. But you'll find that a combination of use strict; and named variables will also make the code waaay more obvious!

    Of course, I could just be talking total cack.... :)
Re: Matching string, then getting next line
by graff (Chancellor) on Mar 09, 2006 at 03:19 UTC
    It would be easier if the file content were stored in an array (or if, as suggested above, you were reading it one line at a time). Something like this -- with some of the initialization steps filled in -- could be worthwhile:
    open( INPUT, "some.file" ) or die $!; my @content; { local $/; @content = split( /[\r\n+]/, <INPUT> ); } my $tag1 = "whatever"; my $tag2 = "blah"; my $i = 0; while ( $i < $#content ) { # don't test very last line $_ = $content[$i++]; print "$content[$i]\n" if (( /35=8/ and /$tag1/ and /$tag2/ ) or ( /35=9/ and /$tag1/ )); }

    I wanted to include the file open and read steps to show how to slurp it directly into an array (rather than slurping to a scalar then splitting to an array, which keeps two copies of the whole file in memory, which makes me itchy).

    BTW, notice that you were using printf with a single scalar arg. Someday, if that string happened to contain "%d" or something similar, you might find the output to be different from what you intended.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://535132]
Approved by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (2)
As of 2020-10-27 04:46 GMT
Find Nodes?
    Voting Booth?
    My favourite web site is:

    Results (256 votes). Check out past polls.