Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sed delete between two patterns deletes until end if second pattern is not found

Tags:

sed

I'm using sed to remove tags in a configuration file, but I accidentally stumbled upon a problem, for which I'll use a basic example:

Contents of numbers.txt file:

0
1
2
3
4
5
6
7
8
9

Delete between two numbers (including the numbers themselves):

sed '/4/,/6/d' numbers.txt

Yields (as expected):

0
1
2
3
7
8
9

But if I remove the 6 line from numbers.txt, I would expect the same command to yield all of numbers.txt since it cannot find the second pattern, but instead it simply deletes everything after the 4 line (presumably because the search for 6 reached the end of the file, so that's the value it returns):

0
1
2
3

My question is: how do I modify the sed statement to simply do nothing in such an event?

like image 437
spiff Avatar asked Oct 13 '25 02:10

spiff


1 Answers

This might work for you (GNU sed):

sed '/4/{:a;$!{N;/6/Md;ba}}' file

Build your own loop and only delete the accumulated lines in the pattern space if the end condition is met.

N.B. The M flag on the end condition to allow matches on multiple lines gathered up in the pattern space.

The /start/,/end/d is a control structure that upon finding start immediately deletes lines until end or the end of the file. Therefore there are two end conditions, the address /end/ or $. As the action (in this case deletion) is immediate, it can not be reversed if the /end/ condition is not met, for this reason the lines to be deleted need to gathered up and deleted or not depending on one of two conditions, either /end/( delete) or $ (do not delete).

  • /4/{...} start address of actions within the curly braces.
  • :a the address of the start of a loop named a
  • $!{...} if not the end of file actions within the curly braces.
  • N append a newline and then the next line to the pattern space.
  • /6/Md end address and delete command if found i.e. this will delete all lines in the pattern space that have been appended by the N command.
  • ba goto command, breaks to the loop address a. This enables the loop mechanism to continue until one of two conditions /6/ or$.

N.B. If the end of file condition is met, the /4/{...} ends and the accumulated lines are printed as normal.

like image 171
potong Avatar answered Oct 15 '25 03:10

potong



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!