delete contents in a file between two markers (selective deletion of lines)

Hello! Small command, lots of power.

Example:

$ cat testcase2
some code
    // feature-x-start
    foo bar
    // feature-x-end
more code
$ cat testcase2 | sed '\|// feature-x-start|,\|// feature-x-end|d'
some code
more code

How and why does this work?

Now the interesting part. Resources to learn from. https://catonmat.net/sed-one-liners-explained-part-three shows the foundation of this recipe and it calls it “Selective Deletion of Certain Lines”, specifically “Print all lines in the file except a section between two regular expressions.”.

It uses a feature that is called “range addresses” in the sed docs:

An address range matches lines starting from where the first address matches, and continues until the second address matches (inclusively):

(emphasis mine)

This clarifies that this always matches (whole) lines.

I have found other names for this sed feature. Depending on what book/resource you’re looking at, this may be called “address range” or “pattern range” or “range match”.

This technique really has little or nothing to do with the sed substitute command which we’re most often using. The d part of the recipe above? Well:

The ‘d’ command deletes the current pattern space

What about those \|?

When using e.g. s/foo/bar/g I am used to the idea that we can use a different delimiter so that we can easily add in a literal forward slash, like in s|foo/|far|g.

This doesn’t work naively with the pattern range. Does it? Internet forums are nice, the older the nicer. Waldner said in 2010 that “It just has to be escaped”. And that’s what the backslash is for.

This allows for using the forward slash in the pattern as I did in

sed '\|// feature-x-start|,\|// feature-x-end|d'

The following example demonstrates that indeed sed here operates in a line-based fashion, i.e. this selective deletion of lines does not work on line fragments:

$ cat testcase1
a test file
   with /Xtremely nice
contents for your
  amusements.
$ cat testcase | sed '\|/Xtremely|,\|for|d'
a test file
  amusements.

I used this in CI. Lots of love for sed.

Leave a Reply

Your email address will not be published. Required fields are marked *

Human? Please fill this out: * Time limit is exhausted. Please reload CAPTCHA.

  1. Jan-Philip Avatar

    Looking for the inverse? https://catonmat.net/sed-one-liners-explained-part-two section 67: “Print section of lines between two regular expressions (inclusive).”

    sed -n '/Iowa/,/Montana/p'