1

I'd like to ask is it possible to combine somehow -v with -A?

I have example file:

abc
1
2
3
ACB
def
abc
1
2
3
ABC
xyz

with -A I can see the parts I want to "cut":

$ grep abc -A 4 grep_v_test.txt
abc
1
2
3
ACB
--
abc
1
2
3
ABC

it there some option to specify something to see only

def
xyz

?

I found this answer - Combining -v flag and -A flag in grep but it is not working for me, I tried

$ sed -e "/abc/{2;2;d}" grep_v_test.txt
sed: -e expression #1, char 8: unknown command: `;'

also

$ sed "/abc/2d" grep_v_test.txt
sed: -e expression #1, char 6: unknown command: `2'

or

$ sed "/abc/+2d" grep_v_test.txt
sed: -e expression #1, char 6: unknown command: `+'

Sed version is:

$ sed --version
GNU sed version 4.2.1

edit1: Based on comment I experimented a little bit with both solution, but it is not working as I want to

for grep -v -A 1 abc I would expect line abc and 1 to be removed, but the rest will be printed awk 'c&&!--c; /abc/ {c=2}' grep_v_test.txt prints just the line containing 2, which is not what I wanted.

Very similar it is with sed

$ sed -n '/abc/{n;n;p}' grep_v_test.txt
2
2

edit2: It seems, I'm not able to describe it properly, let me try again.

What grep -A N abc file does is to print N lines after abc. I want to remove what grep -A will show, so in a file

abc
1
2
3
ACB
def
DEF
abc
1
2
3
ABC
xyz
XYZ

I'll just remove the part abc to ABC and I'll print the rest:

abc
1
2
3
ACB

def
DEF
abc
1
2
3
ABC
xyz
XYZ

so 4 lines will remain... The awk solution prints just def and xyz and skips DEF and XYZ...

Community
  • 1
  • 1
Betlista
  • 10,327
  • 13
  • 69
  • 110
  • Just use `awk` ----> `awk 'c&&!--c; /abc/ {c=5}' file` – fedorqui Aug 11 '16 at 11:37
  • Thanks for the answer it works fine, but still I'd like to know the answer using sed (I'm a bigger friend with that one compared to awk). – Betlista Aug 11 '16 at 11:40
  • Then use [Printing next line with sed](http://stackoverflow.com/a/3820821/1983854) so you get `sed -n "/abc/{n;n;n;n;n;p}" file`. – fedorqui Aug 11 '16 at 11:43
  • Now I understood better previous example, but this is not really working as grep -v, it is not printing not matching lines... – Betlista Aug 11 '16 at 11:48
  • Both one-liners I mentioned do the same: match a line with content "abc" and then print the 5th line after it. – fedorqui Aug 11 '16 at 11:49
  • Yes, I realized that it was not cleared, so I edited the question, to make it clear. I'm pretty sure it's easy to add else branch to awk to print other lines, with sed I'm not so optimistic... – Betlista Aug 11 '16 at 11:55
  • This is weird. With the sample file you provided, you are getting 2 and 2, which are just two lines after the match. My code was printing 5 lines after. Is your sample file really like this? – fedorqui Aug 11 '16 at 11:57
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/120696/discussion-between-betlista-and-fedorqui). – Betlista Aug 11 '16 at 11:59

2 Answers2

2

If I understand you properly, you want to print all the lines that occur 4 lines after a given match.

For this you can tweak the solutions in Extract Nth line after matching pattern and say:

$ awk '/abc/ {c=0} c++>4' file
def
DEF
xyz
XYZ
Community
  • 1
  • 1
fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • Thanks, that seems exactly as what I wanted, but as I said I'm not so big friend with awk... It seems very simple when I see it now... – Betlista Aug 11 '16 at 12:55
  • @Betlista you could try to write this in `sed` but it would probably get crazy, since it is a tool to do things with lines, one by one. I prefer `awk`, since it is good to do things with files taking into consideration all the context. And it is quite neat also :) – fedorqui Aug 11 '16 at 12:57
  • I already like your solution. I wanted something which is as simple to check as grep with/wothout -v and change from `c++ > 4` to `c++ <= 4` is so simple ;-) – Betlista Aug 11 '16 at 13:03
  • That only does what you want because `abc` occurs at the start of the file. If it didn't then that command would skip the first 5 lines anyway. – Ed Morton Aug 11 '16 at 13:24
  • 1
    @Betlista so yes, Ed's solution covers all cases. – fedorqui Aug 11 '16 at 14:58
2

To skip 5 lines of context starting with the initial matching line is:

$ awk '/abc/{c=5} c&&c--{next} 1' file
def
xyz

See Extract Nth line after matching pattern for other related scripts.

wrt the comments below, here's the difference between this answer and @fedorqui's answer:

$ cat file
now is the Winter
of our discontent
abc
1
2
bar

$ awk '/abc/{c=3} c&&c--{next} 1' file
now is the Winter
of our discontent
bar

$ awk '/abc/ {c=0} c++>2' file
bar

See how the @fedorqui's script unconditionally skips the first 2 lines of the file?

Community
  • 1
  • 1
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
  • I do not clearly see what's the difference. When I changed content of the file "abc" -> "x abc" and used same command it worked, so it seems, your statement "That only does what you want because abc occurs at the start of the file." is not correct. It's not clear to me (also on linked page) what this `1` and `{next}` are used for... – Betlista Aug 11 '16 at 13:38
  • 1
    @Betlista I edited my answer to include an example to show you the difference between the 2 scripts. – Ed Morton Aug 11 '16 at 13:57