Subject: Re: bug#26576: -v when used with -C

From: Assaf Gordon <[email-masked]>
Date: Thu, 20 Apr 2017 16:51:19 +0000

Hello,

On Thu, Apr 20, 2017 at 11:26:47AM -0500, Eric Blake wrote:
>On 04/20/2017 10:37 AM, 積丹尼 Dan Jacobson wrote:
>> I want to do
>> $ cat file|some_program
>> but I must must exclude the UGLY line and its two neighbors.
>>
>> OK I have found the UGLY line, and its two neighbors
>> $ grep -C 2 UGLY file
>> bla
>> bla
>> UGLY
>> bla
>> bla
>>
>> but I have no way to exclude them before piping to some_program.
>
>It's very corner case, so I'm not sure it's worth burning an option and
>complicating grep to do this, plus waiting for a future version of grep
>with the proposed new option to percolate to your machines, when you
>already accomplish the same task using existing tools (admittedly with
>more complexity).
>

If I may suggest the following sed program:

  $ cat file
  a
  b
  c
  bla1
  bla2
  UGLY
  bla3
  bla4
  e
  f
  g

  $ sed -n ':x 1,2{N;bx} ; /UGLY/{ N;N;z;bx }; /./P;N;D' file
  a
  b
  c
  e
  f
  g

The combination of N/P/D commands use sed's pattern space
as a fifo buffer (N appends a new line, P prints the last line,
D deletes the last line).
In between, if the pattern space contains the marker UGLY,
the entire buffer is deleted and the cycle is restarted.

Specifically:

1. ':x 1,2{N;bx}' => Load the buffer with the first two lines.

2. '/UGLY/ {N;N;z;bx}' => If the marker is found in the pattern
   space (which should contain 3 lines now),
   consume two more lines (N;N), clear the buffer (z) and
   jump to the beginning.
   'z' is GNU extension. It can be replaced with 's/.*//'.

3. '/./P' => If the pattern space isn't empty, print up to
   the first line;

4. 'N;D' => Read the next line from the input file and append
   it to the pattern space, Delete the last line from the
   pattern space (the same line that was printed with 'P').

The following program can be used to learn a bit more about how 
the N/P/D commands work. It uses 'l' to the print content
of the pattern space, and you can see it behaves like a FIFO:

  $ sed -n ':x 1,2{N;bx} ; l;P;N;D' file
  a\nb\nc$
  a
  b\nc\nbla1$
  b
  c\nbla1\nbla2$
  c
  bla1\nbla2\nUGLY$
  bla1
  bla2\nUGLY\nbla3$
  bla2
  UGLY\nbla3\nbla4$
  UGLY
  bla3\nbla4\ne$
  bla3
  bla4\ne\nf$
  bla4
  e\nf\ng$
  e

More information about sed's buffers can be found here:
 https://www.gnu.org/software/sed/manual/sed.html#advanced-sed

hope this helps,
regards,
 - assaf