Reputation: 26402
Deleting the match and two lines before it works:
sed -i.bak -e '/match/,-2d' someCommonName.txt
Deleting the match and two lines after it works:
sed -i.bak -e '/match/,+2d' someCommonName.txt
But deleting the match, two lines after it and two lines before it does not work?
sed -i.bak -e '/match/-2,+2d' someCommonName.txt
sed: -e expression #1 unknown command: `-'
Why is that?
Upvotes: 3
Views: 2725
Reputation: 204099
FWIW this is how I'd really do the job (just change the b
and a
values to delete different numbers of lines before/after match
is found):
$ cat file
1
2
3
4
5 match
6
7
8
9
$ awk -v b=2 -v a=2 'NR==FNR{if (/match/) for (i=(NR-b);i<=(NR+a);i++) skip[i]; next } !(FNR in skip)' file file
1
2
8
9
$ awk -v b=3 -v a=1 'NR==FNR{if (/match/) for (i=(NR-b);i<=(NR+a);i++) skip[i]; next } !(FNR in skip)' file file
1
7
8
9
Note that the above assumes that when 2 "match"s appear within a removal window you want to base the deletions on the original occurrence, not what would happen after the first match being found causes the 2nd match to be deleted:
$ cat file2
1
2
3
4 match
5
6 match
7
8
9
$ awk -v b=2 -v a=2 'NR==FNR{if (/match/) for (i=(NR-b);i<=(NR+a);i++) skip[i]; next } !(FNR in skip)' file2 file2
1
9
as opposed to the output being:
1
7
8
9
since deleting the 2 lines after the first match
would delete the 2nd match
and so the 2 lines after THAT would not be deleted since they no longer are within 2 lines after a match
.
Something else to consider:
$ diff --changed-group-format='%<' --unchanged-group-format='' file <(grep -A2 -B2 match file)
1
2
8
9
$ diff --changed-group-format='%<' --unchanged-group-format='' file2 <(grep -A2 -B2 match file2)
1
9
That uses bash and GNU diff 3.2, idk if/which other shells/diffs would support those constructs/options.
Upvotes: 1
Reputation: 10039
sed -i .bak '/match/,-2 {/match/!d;};/match/,+2d' YourFile
try this (cannot test here, -2
is not available in my sed version)
Upvotes: 3
Reputation: 44191
sed
operates on a range of addresses. That means either one or two expressions, not three.
/match/
is an address which matches a regex.
-2
is an address which specifies two lines before
+2
is an address which specifies two lines after
Therefore:
/match/,-2
is a range which specifies the line matching match
to two lines before.
/match/-2,+2d
, on the other hand, includes three addresses, and thus makes no sense.
To delete two lines before and after a pattern, I would recommend something like this (modified from this answer):
sed -n "1N;2N;/\npattern$/{N;N;d};P;N;D"
This keeps 3 lines in the buffer and reads through the file. When the pattern is found in the last line, it reads two more lines and deletes all 5. Note that this will not work if the pattern is in the first two lines of the file, but it is a start.
Upvotes: 4
Reputation: 328754
I don't have a complete solution but an outline: sed
is a pretty simple tool which doesn't do two things at once. My approach would be to run sed
once deleting the two lines after the pattern but keeping the pattern itself. The result can then be piped to sed
again to remove the pattern and the two lines before.
Upvotes: 3