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