awksedgreptac

Delete 2 lines of text before the line containing the matching pattern using sed?


I have a file containing the following lines:

aaa
bbb
ccc
pattern
eee
fff
ggg
pattern
hhh

I would like to delete 2 lines before the last matching pattern in the file. The expected output is:

aaa
bbb
ccc
pattern
eee
pattern
hhh

I tried - sed -i '/pattern/{N;N;d;}' file but it didn't work. There was no change to the file.

I also tried - tac file | sed '/pattern/,+2 d' | tac > tmpfile && mv tmpfile file but this also deleted the line containing the matching pattern.

My sed version is sed (GNU sed) 4.7.

Any help would be much appreciated. Thanks.


Solution

  • sed is the wrong tool for this. Any time you want to edit a file, especially if you want to look backwards after some matching bit, ed is almost always a better option, as it's designed to work with files, not a stream of lines always moving forward.

    ed -s file.txt <<'EOF'
    ?pattern?-2;+1 d
    w
    EOF
    

    or if a heredoc isn't convenient

    printf '%s\n' '?pattern?-2;+1 d' w | ed -s file.txt
    

    will first set the current line to the one two before the last one matching pattern, and then delete that line and the one following (So the two lines preceding that last match of pattern), and finally write the modified file back out.