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.
So it sounds like you are asking for some sort of new --invert-output, which toggles which lines to display. Revisiting my example, it would change: $ seq 10 | grep -C 2 5 3 4 5 6 7 into: $ seq 10 | grep -C 2 5 --invert-output 1 2 -- 8 9 10 as well as: $ seq 10 | grep -C 2 -v 5 1 2 3 4 5 6 7 8 9 10 $ seq 10 | grep -C 2 -v '[3-8]' 1 2 3 4 -- 7 8 9 10 into: $ seq 10 | grep -C 2 -v 5 --invert-output $ seq 10 | grep -C 2 -v '[3-8]' --invert-output 5 6 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). For example, you can use sed twice if the data is in a file that can be re-read or easily regenerated (in this case, I'm skipping d, h, and any line within -C1 of the ugly lines): $ printf %s\\n a b c d e f g h i j > file $ ugly=$(sed -n '/[dh]/ =' file) $ sed "$(for line in $ugly; do echo "$((line-1)),$((line+1))d;"; done)" file a b f j Or it should be easy enough to write an awk script that stashes all input lines into one array, then checks for regular expression matches, and sets multiple entries in a corresponding poison array to 1 (based on how many lines of context you want to poison), then in an END block only print out lines if the corresponding poison[] entry is not 1. Although I'll leave that as an exercise for the reader. -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org
signature.asc
Description: OpenPGP digital signature