Search code examples
linuxbashtextsed

Using sed to remove all lines between two patters if text is found between them


I have a file

###
A
B
C
@@@
###
D
E
F
@@@
###
G
H
I
@@@

I want to remove all lines between ### and @@@ (inclusive) if it contains A

How can I achieve this ?

expected result

###
D
E
F
@@@
###
G
H
I
@@@

I have tried

sed "/###/,/@@@/d"

but that is removing everything.

If we can have multiple text patterns like remove everything between ### and @@@ if it contains either 'A' or 'D' would be even helpful.

Thanks.


Solution

  • You can use

    sed '/###/{:a;N;/@@@/!ba;/A/d}' file
    

    Details:

    • /###/ - looks for a ### and once it is found,
    • :a - set a label at the current location
    • N - reads the next line appending it to pattern space
    • /@@@/!ba - if there is @@@ stop processing block, else, go to a label
    • /A/d - if A is inside the block matched, delete it.

    See an online test:

    #!/bin/bash
    text=$(echo -e '###\nA\nB\nC\n@@@\n###\nD\nE\nF\n@@@\n###\nG\nH\nI\n@@@')
    sed '/###/{:a;N;/@@@/!ba;/A/d}' <<< "$text"
    

    Output:

    ###
    D
    E
    F
    @@@
    ###
    G
    H
    I
    @@@