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

I was lurking yesterday when someone asked about a one-liner to find a pattern, then print the next 10 lines. I came up with a rough approximation, but would like to know the real answer:
perl -ne '/pattern/?$test=1:{($test>=1)?$test++:next}&&($test>=2&&$tes +t<=11)?print:next' <filename>
What is the real answer? UPDATE: Co-worker helped shorten it:
perl -ne '/pattern/?$t=1&&print:{($t)?$t++:""}&&($t&&$t<12)?print:""' +filename
Piroufreek.

Replies are listed 'Best First'.
Re: grep -A10 oneliner?
by Roy Johnson (Monsignor) on Apr 14, 2005 at 19:53 UTC
    As I posted the other day: perl -ne 'print if $.=/pattern/..10' Update: using // instead of ?? (originally thought you only wanted the first match)

    Caution: Contents may have been coded under pressure.

      It fails in two fashions. It only displays 9 lines after, not 10, it doesn't support overlapping ranges.

        The first is trivial: set the number to be the total number of context lines you want, including the matched pattern line.

        The second is a little trickier:

        perl -ne 'print if $.=/pattern/?1:2..10'
        In this case, it will print 10 lines after the match.

        Update: so tricky, in fact, that you can't do it with the range operator. So there's no point in using $.. So you just do

        perl -ne 'print if$c=/pattern/?11:$c&&$c-1'
        or any of the other solutions here. Sigh.
        One that doesn't require you to add one to the number you put in:
        perl -ne 'print if(/pattern/?$c=10:$c--)>0'

        Caution: Contents may have been coded under pressure.
Re: grep -A10 oneliner?
by Roy Johnson (Monsignor) on Apr 14, 2005 at 21:41 UTC
    I think this is fully golfed, yet reasonably readable:
    perl -ne 'print if/pattern/?$c=10:$c-->0'

    Caution: Contents may have been coded under pressure.
Re: grep -A10 oneliner?
by Fletch (Bishop) on Apr 14, 2005 at 19:46 UTC
    perl -lne '$c=11if/pattern/;$c--,print if$c' file

    FORE!: Removed unneeded space between if $c.

Re: grep -A10 oneliner?
by ikegami (Patriarch) on Apr 14, 2005 at 19:44 UTC

    How about the following: (Not golfed)

    perl -ne "$i = 11 if /pattern/; if ($i) { $i--; print; }"
Re: grep -A10 oneliner?
by dragonchild (Archbishop) on Apr 14, 2005 at 19:41 UTC
    perl -ne 'next unless /pattern/;($i++<10)?(print($_)):(last)' <filenam +e>

    Update: ikegami is absolutely correct. Tested version that works:

    -ne 'next unless /pattern/;print scalar <> for 1..10;last' <filename>

      Doesn't work. It only displays the matches.

      Update: The updated solution also fails. It doesn't support overlapping ranges.

Re: grep -A10 oneliner?
by tlm (Prior) on Apr 14, 2005 at 19:52 UTC
    perl -ne '(/pattern/..$x++>9)&&print'

    OK, that's my best.

    the lowliest monk

      Not quite. It doesn't support overlapping ranges.

Re: grep -A10 oneliner?
by ambrus (Abbot) on Apr 14, 2005 at 19:48 UTC

    That's grep -A, not grep -b. Grep -b prints byte offsets of the matches.

    Update: grep -A10, more precisely.

      Why not both?

      # grep -b -A10 pattern file perl -ne '$c=11if/pattern/;$d=$c<11?"-":":";$t||=0;$c--,print"$t$d$_"i +f$c;$t=tell' file

      Update: This produces the same output as GNU diff which prints --\n between groups farther than the -A amount of lines apart.

      perl -lne 'if(/pattern/){print"--"if!$c&&$t;$c=11};$d=$c<11?"-":":";$t +||=0;$c--,print"$t$d$_"if$c;$t=tell' file
Re: grep -A10 oneliner?
by ysth (Canon) on Apr 14, 2005 at 22:21 UTC
    FWIW, my entry:
    perl -wne'print if /pattern/..(/pattern/&&($.=-10),$.>=0)'