sed Command – Why Does sed s/// Remove a Particular String?

sed

I have two files: junk.txt and lines.txt

$>cat junk.txt
This is a junk text
$>cat lines.txt
Line1
Line2
Line3
Line4

When I fire the following sed script

 sed -i -e  "/Line3/r junk.txt" -e "s///" lines.txt

I get this output:

Line1
Line2

This is a junk text
Line4

As you can see, Line3 is no more there. Ok, the /Line3/r junk.txt part finds the text in the lines.txt matching Line3 and appends the contents of the junk.txt. But why does the s/// command remove exactly the matched line?

To be honest, that's the behavior I need but I want to know why it behaves like that.

Best Answer

When the editing command s is invoked with an empty regular expression, it reuses the expression most recently used. In this case, it reuses Line3 from the matching of it earlier. This applies to // (empty regular expressions) in both the s command and in address ranges.

Your command could also be written, without this feature, as

sed -i -e '/Line3/r junk.txt' -e 's/Line3//' lines.txt

The Line3 text is removed because it is replaced by nothing.

You would sometimes see this in constructs like

/expression/ {
    s//replacement/
    # other code here
}

The POSIX specification for sed formulates this as

If an RE is empty (that is, no pattern is specified) sed shall behave as if the last RE used in the last command applied (either as an address or as part of a substitute command) was specified.

Related Question