The challenge to turn this into a Perl one-liner proved too enticing.

I've assumed that the pattern can match more than one time in the file, but that if one of the lines deleted following the match contains the same pattern again, it gets ignored. This may or may not be an edge condition that you need to be aware of.

My approach builds a buffer of read lines. When the buffer reaches five lines long, the first line in gets shifted off the FIFO queue and printed. If the "match" line is detected, that line along with the buffer will be discarded. Then three more lines are read but ignored. Finally, upon completion of reading the file, whatever lines are still in the buffer get printed too.

The following is a long-hand version of my script first:

use strict; use warnings; my @buffer; my $re = qr/10/; while (<DATA>) { if ( $_ =~ $re ) { @buffer = (); my $count = 0; while( <DATA> and $count++ < 2 ){}; } else { push(@buffer, $_); if( defined( $buffer[5] ) ) { print shift(@buffer); } } } print @buffer; __DATA__ Line 01 Line 02 Line 03 Line 04 Line 05 Line 06 Line 07 Line 08 Line 09 Line 10 Line 11 Line 12 Line 13 Line 14 Line 15 Line 16 Line 17 Line 18 Line 19 Line 20

To convert this to a one-liner, we'll use the -n option, which implicitly creates the outer while(){} loop. The only problem with the -n option is that the remaining items in the buffer would get dropped if we didn't come up with a plan to deal with them after the implicit while() loop. The way to do this is to define an END{} block. The END{} block gets executed just after the while() loop completes, and just before the one-liner terminates execution. The -i.bak switch is used to specify in-place editing with the creation of a backup file. And as you see by looking at the code, we're hard-wiring the match value. Why not? One liners are disposable.

Here's how it looks:

perl -ni.bak -e "if(/10/){@buf=();$cnt=0;while(<> and $cnt++<2){}}else +{push @buf,$_;if(defined $buf[5]){print shift(@buf)}}END{print @buf}" + mytest.txt

Enjoy!


Dave


In reply to Re: Regex question by davido
in thread Regex question by jamsda

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.