James Ko
James Ko

Reputation: 34629

Grep: How to exclude lines before/after if a line contains an unwanted string?

I'm running a command with diff on 2 very big assembly dumps. I see lots of output like this:

903c903
< ; Emitting BLENDED_CODE for generic X86 CPU
---
> ; Emitting BLENDED_CODE for Pentium 4
995c995
< ; Emitting BLENDED_CODE for generic X86 CPU
---
> ; Emitting BLENDED_CODE for Pentium 4
1123c1123
< ; Emitting BLENDED_CODE for generic X86 CPU
---
> ; Emitting BLENDED_CODE for Pentium 4
1191c1191
< ; Emitting BLENDED_CODE for generic X86 CPU
---
> ; Emitting BLENDED_CODE for Pentium 4
1278c1278
< ; Emitting BLENDED_CODE for generic X86 CPU
---
> ; Emitting BLENDED_CODE for Pentium 4
1347c1347
< ; Emitting BLENDED_CODE for generic X86 CPU
---
> ; Emitting BLENDED_CODE for Pentium 4
1546c1546
<        inc      dword ptr [ebp-10H]
---
>        add      dword ptr [ebp-10H], 1
1552c1552
<        inc      esi
---
>        add      esi, 1

I don't really want to see the lines that contain "Pentium 4" or "generic X86 CPU"; specifically, if there is a line that contains "Pentium 4" I want to exclude that line and the 3 lines above it.

Is it possible to do this using grep? I know about grep -v 'Pentium 4', but that only works for single lines. I can't do grep -v -- '---' obviously, since there are some valid diffs that contain a triple-dash.

If the grep query were run on the above code, the result should be

1546c1546
<        inc      dword ptr [ebp-10H]
---
>        add      dword ptr [ebp-10H], 1
1552c1552
<        inc      esi
---
>        add      esi, 1

Upvotes: 1

Views: 1182

Answers (4)

Ed Morton
Ed Morton

Reputation: 204638

$ awk '{r=r $0 ORS} (NR%4)==0{if (!/Pentium 4/) printf "%s", r; r=""}' file
1546c1546
<        inc      dword ptr [ebp-10H]
---
>        add      dword ptr [ebp-10H], 1
1552c1552
<        inc      esi
---
>        add      esi, 1

Upvotes: 0

dbosky
dbosky

Reputation: 1641

I like process substitution here. Let's assume file_a is:

; Emitting BLENDED_CODE for generic X86 CPU                                                                                                                                                          
inc      dword ptr [ebp-10H]

And file_b is:

; Emitting BLENDED_CODE for Pentium 4
add      dword ptr [ebp-10H], 1

Running

diff -I "^;" file_a file_b

will return:

1,2c1,2
< ; Emitting BLENDED_CODE for generic X86 CPU
< inc      dword ptr [ebp-10H]
---
> ; Emitting BLENDED_CODE for Pentium 4
> add      dword ptr [ebp-10H], 1

Which isn't exactly that you want I guess. However, when you try with process substitution i.e.

diff <(grep -v '^;' file_a) <(grep -v '^;' file_b)

you will get:

1c1
< inc      dword ptr [ebp-10H]
---
> add      dword ptr [ebp-10H], 1

Upvotes: 4

twalberg
twalberg

Reputation: 62519

You can use process substitution in bash to strip out the comments from the source files:

diff <(grep -v '^;' file1.s) <(grep -v '^;' file2.s)

Upvotes: 1

hek2mgl
hek2mgl

Reputation: 158250

You can use the -I option of diff to exclude lines which match a certain pattern from the diff:

diff -I 'Pentium 4\|generic X86 CPU' file1 file2

The pattern must be matched by both lines, that's why you need to use the | (logical or) operator to make the pattern match the original and the change.

Upvotes: 1

Related Questions