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

Hello again.

I am trying to write a script that will read in a file into an array line by line. When it gets to the line starting with arcserve.nlm, I want my script to put that line and all other lines after that one until it reaches 2 blank lines into a temporary file. This arcserve.nlm will be somewhere in the middle of the file, but the line will start with arcserve.nlm.

Please help! I am having problems jumping to the line beginning with arcserve.nlm, then starting my conditions with this line, giving me every line until I reach 2 blank lines together. Below is what I have started:

use strict; use File::Basename; ##******** Variables ********## my $filepath = 'c:\a\netware'; my $dump = 'Netware_hw.txt'; my $arc = 'ARCSERVE.NLM'; my $serverfile = 'dallas.txt'; opendir (SOFTWARE, "$filepath"); chdir $filepath; open (SERVER, "<$serverfile") or die "Can't open the file\n"; open (OUTPUT, ">>$filepath\\$dump"); print OUTPUT "$name~"; my @lines= <SERVER>; foreach my $line (@lines) { if ($line =~ m/$arc/) { split(/^\n/; print OUTPUT "$line~";} } } close (OUTPUT); closedir (SERVER); closedir (SOFTWARE);

Thanks in advance for any assistance anyone can provide me with!

Replies are listed 'Best First'.
(jeffa) Re: Searching for variable then blank lines
by jeffa (Bishop) on Mar 14, 2002 at 05:27 UTC
    If you know that dallas.txt is not going to be terribly large, then you can 'slurp' the entire file into a scalar (instead of an array) and use a regex. The trick is to use the 's' modifier to allow . to match newlines and the 'm' modifier to allow ^ to match the start of any line. See perlre for more.
    my $slurped = do {local $/; <SERVER>}; # EEK! i see my mistake now! this line #my ($temp) = $slurped =~ /($arc.*)\n\n/sm; # should have been my ($temp) = $slurped =~ /^($arc.*)\n\n/sm; print OUTPUT $temp;
    P.S. Use these three lines instead of declaring the array @lines and the entire foreach loop if you wish to test this suggestion. It doesn't solve your problem about understanding conditional looping, but it does provide another way to solve the problem at hand.

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
      I think (maybe wrong) that he wants something more like:
      /($arc.*?\n)\n\n/s

      since the block ends in the first two blank lines and two empty lines are 3 line feeds.

      Tiago
        UPDATE - sorry tstock, i see what happened - i forgot to add the ^ to my example above ... most sorry :O

        Try it out: ;)

        use strict; my $arc = 'ARCSERVE.NLM'; my $slurped = do {local $/; <DATA>}; #my ($temp) = $slurped =~ /^($arc.*)\n\n/sm; my ($temp) = $slurped =~ /($arc.*?\n)\n\n/s; print $temp; __DATA__ not this one or this one asdffARCSERVE.NLM or even this one ---------------- ARCSERVE.NLM sign here and here and here and here and here ---------------- but not here blah blah blah blah blah blah
        I'm sticking to my answer (well, if i had COPIED IT CORRECTLY!!! bad jeffa!) , remember that the 's' modifier allows . to match that newline. Your suggestion would be pretty much the same (and i will admit possibly a bit safer) except you NEED 'm' and ^ in case ARCSERVE.NLM appears in the middle or end of a line.

        jeffa

        L-LL-L--L-LL-L--L-LL-L--
        -R--R-RR-R--R-RR-R--R-RR
        B--B--B--B--B--B--B--B--
        H---H---H---H---H---H---
        (the triplet paradiddle with high-hat)
        
Re: Searching for variable then blank lines
by tstock (Curate) on Mar 14, 2002 at 04:51 UTC
    1. set a true/false tag when arcserve is found
    2. write lines to file
    3. exit if two blank lines found in a row
    untested:
    my ($s, $b); foreach my $line (@lines) { if ($line =~ /^\n$/i) { $b++; last if (($b == 2) && $s); } else { $b = 0; } if ($line =~ /^$arc/) { $s = 'true'; } if ($s) { print OUTPUT $line; } }

    Also, you can skip the array part and do
    for my $line (<SERVER>) {

    Tiago
      Thanks for putting me in the right direction. I'm still confused. Will this jump down into my file, start where "arcserve.nlm" is found and print out every line, line by line, until two consecutive blank lines are found, then exit? I don't know if I was clear enough about what I was trying to do. If this is true, where should I insert this code into my scrip? Again, thanks for your help.
        yes, it does what I think you want.

        $s is true if you found the starting string, false otherwise
        $b only gets to 2 if it finds two blank lines in a row
        we only end the loop if we found two blank lines ($b) and a start ($s)
        we only print if we found a start ($s)

        (might make more sense if read from the bottom up, but then it wouldn't work correctly)

        This code works for big and small files alike, but for smaller files you can always try a regular expression if it's easier for you. If you don't use the array, this code actually has no memory problems handling very large files.

        Tiago