1

In a bash script, I'm trying to delete all contents between starting with AAA (inclusive), and right up to BBB (exclusive). So therefore everything from AAA through just before BBB, and BBB would still be outputted. I came up with the line below, but it incorrectly is removing BBB also. Appreciate any help.

sed -i '/AAA/,/BBB/d' file.txt
5
  • I'm sure this is a duplicate but I can't find it ... sed '/AAA/,/BBB/{/BBB/!d}' file ? Commented May 29, 2020 at 2:04
  • what do you mean it's a duplicate? i can't test right now unfortunately but you sure about the answer? thanks.
    – Matt
    Commented May 29, 2020 at 2:07
  • Related question on SO: stackoverflow.com/questions/16633308
    – Freddy
    Commented May 29, 2020 at 2:10
  • Could the lines containing AAA and BBB contain other stuff? Like fooAAAbar or fooBBBbar? Might be a good idea to provide some example input data. Commented May 29, 2020 at 2:27
  • the lines both start with AAA and BBB but have some characters after it
    – Matt
    Commented May 29, 2020 at 2:30

1 Answer 1

1

If AAA and BBB are at the beginning of a line

Using sed to delete range of lines except the end pattern has the answer to your question:

sed -i '/AAA/,/BBB/{/BBB/!d}' file.txt

Example input:

AAA remove1
remove2
BBB keep3

Example output:

BBB keep3

If they can occur somewhere in the middle of a line

You could use a regular expression:

sed -izE 's/(.*?)AAA.*?(BBB.*)/\1\2/g' file.txt

Parantheses are grouping parts of the regular expression so we can refer to their content by \1 (first capture group) and \2 (second capture group) later. .* matches any character (.) 0 or more times (*). The following question mark makes the * "lazy" which ensures it matches the shortest string possible (for AAA foo1 BBB AAA bar2 BBB AAA.*?BBB would match AAA foo1 BBB rather than AAA foo1 BBB AAA bar BBB).

The -z parameter separates lines by a NUL character rather than a line break allowing the regular expression to handle multiple lines.

Example input:

keep1 AAA remove1
remove2
remove3 BBB keep3

Example output:

keep1 BBB keep3
6
  • no they're on different lines of the file, several lines apart
    – Matt
    Commented May 29, 2020 at 2:08
  • BBB starts a new line, and I want the lines to all be deleted from the line that starts with AAA through the line right before BBB
    – Matt
    Commented May 29, 2020 at 2:09
  • Is that going to work any better or different than the simple sed '/AAA/,/BBB/{/BBB/!d}' shown above?
    – Matt
    Commented May 29, 2020 at 2:40
  • @Matt I updated my answer according to your more detailed requirements. Commented May 29, 2020 at 2:43
  • the lines both start with AAA and BBB but have some characters after each (e.g. AAAbbb390-444444). There are no other instances of AAA or BBB in the file. That mean the sed -i '/AAA/,/BBB/{/BBB/!d}' file.txt will work?
    – Matt
    Commented May 29, 2020 at 2:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .