Search code examples
bashsedbsd

Use sed to delete line, and the one below if it contains 1 pattern, but not another


Found a couple of examples similar to what I want but they don't work for me, or others judging by the comments.

I want this

#Hello my name is Chris
next line of random txt
#Hello my name is Bob
next line of random txt
Hello Ana is my name #
next line of random txt
Another Line

to be this

#Hello my name is Chris
next line of random txt
Hello Ana is my name #
next line of random txt
Another Line

Lines that contain "#" but not "Chris" or "Ana" get deleted along with the line below them.


Solution

  • Given input:

    #Hello my name is Chris
    next line of random txt 1
    #Hello my name is Bob
    next line of random txt 2
    Hello Ana is my name #
    next line of random txt 3
    Another Line
    

    Either the script:

    sed -e '/#/ { /Chris/b' -e '/Ana/b' -e 'N; d; }' data
    

    or the script:

    sed -E \
        -e '/#/ {
                     /(Chris|Ana)/b
                     N
                     d
                }' \
        data
    

    generates:

    #Hello my name is Chris
    next line of random txt 1
    Hello Ana is my name #
    next line of random txt 3
    Another Line
    

    This seems to match your specification. The first doesn't even use extended regular expression (ERE) syntax, so it is maximally portable, but the second shows that it could easily be modified to use ERE syntax. With BSD sed, you can't have a semicolon after the branch (b) command; what would follow has to go on another line or in another -e argument. The b without an explicit label means 'branch to end of script'.