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

Hi all, I have to read severals line of a document in perl. I wrote a program but with that am able to read only lines by line. eg if i have a file in which contents are:
process jkdgf jdk jhfk end process process jhdk jfka end process

I have to read data betwenn process and end process. But am not able to. my code is
while(<WORDLIST>) { if (/process/) #check for process { print "$_"; if (/end process/) { last; } }} close (WORDLIST);

Am just able to read only
process jkdgf end process
as output.... i want output to be as
jdk jhfk jfka
Many Thanks in advance..

Replies are listed 'Best First'.
Re: read multi lines of a file in perl
by richb (Scribe) on Nov 05, 2008 at 14:04 UTC

    Do you want (1) to read only the lines

    jdk jhfk

    Or (2) should your output also include the start and stop reading tokens, like

    process jkdgf jdk jhfk end process
    ?

    For (1), the following code does the trick.

    use strict; use warnings; my $print_flag = 0; while (<DATA>) { if (/end process/) { last; } elsif (/process/) { $print_flag = 1; } else { print if $print_flag; } } __DATA__ ghklg process jkdgf jdk jhfk end process

    Output:

    C:\Perl\src>perl 721648.pl jdk jhfk
      Hi Richb, Thanks for ur reply.. But i still have a small problem.. as this is able to check for only one loop and not repeated loop.. eg
      process lkhls ksjhfk end process process kfhls kfh end process
      i want output as
      ksjhfk kfh
      Thanks....
        flipflop operator to the rescue:
        perl -lne 'print if /^process/ .. /^end process/ and not /^process/ and not /^end process/' process lkhls ksjhfk end process process kfhls kfh end process
        apparently does what you want:
        ksjhfk kfh
        []s, HTH, Massa (κς,πμ,πλ)
Re: read multi lines of a file in perl
by gwadej (Chaplain) on Nov 05, 2008 at 14:54 UTC

    You might also consider the flip-flop operator (see Flipin good, or a total flop?)

    In your problem, the code would look something like:

    while(<WORDLIST>) { if( /^process/ .. /end process/ ) { #recognize and skip first delimiter next if /^process/; #recognize and skip end delimiter next if /end process/; # do something with the middle. print; } }

    This does have the advantage that it restarts if you hit another line starting with process. Obviously, you can also do something special with the start and end points.

    Of course, if you don't need to know when the data starts and stops, you could just do

    while(<WORDLIST>) { next if /^process/ or /^end process/; print; }
    G. Wade
      while(<WORDLIST>) { next if /^process/ or /^end process/; print; }

      You could consider combining the two matches into one (I would also use unless but I know that's not to everyone's taste).

      while( <WORDLIST> ) { print unless m{^(?:end\s)?process}; }

      I hope this is of interest.

      Cheers,

      JohnGG

        I probably would combine them (and use unless), but I was keeping it simple for early morning.<grin/>

        G. Wade
Re: read multi lines of a file in perl
by markov (Scribe) on Nov 05, 2008 at 13:55 UTC
    The logic of your code is wrong: your print will only happen when the line contains /process/. Try:
    local $_; while(<WORDLIST>) { last if /process/; } while(<WORDLIST>) { print; last if /end process/; }
    (many more compact notations for the same exist)
      Hi Markov, Thanks for ur reply.. But i still have a small problem.. as this is able to check for only one loop and not repeated loop.. eg
      process lkhls ksjhfk end process process kfhls kfh end process
      i want output as
      ksjhfk kfh
      Thanks....
        Do this if what only what you require is the bit between:
        print grep { !/process/ } <>;
        perl <script>.pl <input>.txt

        prints
        ksjhfk kfh

        You could also put this in an array
        my @process = grep { !/process/ } <>;
        However this would just be each element for each line. If you wanted them grouped you need something more complex using assertions ( if you do it the inefficent way like i have )
        John,

        UPDATE: This would group them
        { local undef $/; print split /process \s \w+ (.+?) end \s process/xms, <>; }

        P.S. Don't actually use these methods of doing it, There just other ways to do it.
Re: read multi lines of a file in perl
by ccn (Vicar) on Nov 05, 2008 at 13:42 UTC
Re: read multi lines of a file in perl
by flamewise (Initiate) on Nov 05, 2008 at 15:53 UTC
    How about something like:
    my $printing; while(<WORDLIST>) { $printing = 0 if (/^end process/); print if ($printing); $printing = 1 if (/^process/); }
    You can move the "print if ($printing);" line around a little to influence whether the starting or ending lines should be printed, too.
Re: read multi lines of a file in perl
by hangon (Deacon) on Nov 05, 2008 at 18:53 UTC

    Given your example, unless I misunderstand this should be all you need:

    while (<WORDLIST>){ next if /process/; print; }