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

I have a file with below contents ramaabnnc ssddwer.... tool error I need to delete exactly 10 lines above the matched line. Lets say I match for "toolerror" I need to delete 10 lines above that in the files.. Any pointers on doing the same will be helpful.

Replies are listed 'Best First'.
Re: Delete 10 lines before matched line
by GrandFather (Saint) on Mar 11, 2010 at 10:00 UTC

    The usual mantra at this point is "what have you tried". My guess is you haven't tried anything at all. In fact I bet you haven't even thought hard about it (go ahead, prove me wrong - I'd love to be wrong about this). So lets map the problem into a different domain and see where it gets us:

    Consider how you would do it if the lines were instead boxes on a conveyor belt and you had the same problem - remove the 10 boxes that have just gone past if the 10th has a red X on it. If you are sitting right at the end of the belt where the boxes fall off into the hopper of doom you're stuffed. So move your seat along the belt 10 boxes in the direction they are coming from. Now when the red X'd box comes along you have the 10 boxes where you can get at em and remove them from the belt before the fall into the hopper.

    Now all you've got to do is figure out how to translate that into Perl. I'll let you think about it a while before giving further hints. ;)


    True laziness is hard work
Re: Delete 10 lines before matched line
by Corion (Patriarch) on Mar 11, 2010 at 09:50 UTC
Re: Delete 10 lines before matched line
by jmcnamara (Monsignor) on Mar 11, 2010 at 10:46 UTC

    Here is a one way to do it:
    #!/usr/bin/perl use strict; use warnings; my @buffer; my $buffer_size = 10; my $match = qr/toolerror/; # Read a file from STDIN. while ( my $line = <> ) { if ( $line =~ /$match/ ) { # Discard the buffered lines. @buffer = (); # Print the matched line. print $line; } else { # Store non matching lines in a buffer. push @buffer, $line; # Maintain the buffer at a max size. if ( @buffer > $buffer_size ) { print shift @buffer; } } } # Print any remaining buffered lines. print @buffer; __END__

    --
    John.

      # Discard the buffered lines. @buffer = (); # Print the matched line. print $line;
      should be
      # Discard the buffered lines. @buffer = $line;

        Yes it should.

        I thought of that and thought that the OP probably didn't want the matched line deleted or they would have said so. In which case I thought that they would only want 10 lines or less deleted back to the last match. Which leaves me doing a lot of ass of you and me-ing.

        However, your modification is definitely more correct in the general case.

        --
        John.