I need to frequently comment/uncomment a line containing a string with "#". For example:

Don't touch this line.
Touch this LINE instead.


Don't touch this line.
#Touch this LINE instead.

I was able to comment with sed, but had problem to uncomment. I tried command

sed 's/^#\(.*\)LINE/\1/' hosts

It did put a "#" at the beginning, but also removed LINE and the following characters, which made it:

Don't touch this line.
#Touch this 

What's the proper way to do it?


The proper way is to make s work only on lines that match a certain pattern, the substitution can be quite simple then.

This will remove leading # from lines that contain LINE:

sed '/LINE/ s/^#//'

This will remove all leading # characters:

sed '/LINE/ s/^#*//'

This will add one # character:

sed '/LINE/ s/^/#/'

Obviously you cannot remove # that isn't there, but you can add # while a leading # is already there. An improvement to the above command that doesn't modify already commented lines:

sed '/^\([^#].*\|\)LINE/ s/^/#/'

It detects ^LINE or ^[^#].*LINE where ^ matches the beginning of the line and [^#] matches a non-#. It's possible to improve the command further, so # with leading blanks at the beginning of a line will not be commented out again; I won't do this here.

Anyway, use /regex/ s…. If your regex happens to contain slashes, escape them with \; or choose another character to embrace the regex, but then you need to escape the opening one (e.g. \@regex@ s…).

  • Works like a charm! Thank you @Kamil Maciorowski!
    – fiedel
    Dec 21 '20 at 18:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.