Remove comments from file but preserve strings

Remove comments from file but preserve strings containing the comment symbol

sed '/#/!b;s/^/\n/;ta;:a;s/\n$//;t;s/\n\(\("[^"]*"\)\|\('\''[^'\'']*'\''\)\)/\1\n/;ta;s/\n\([^#]\)/\1\n/;ta;s/\n.*//' file


/#/!b if the line does not contain a # bail out
s/^/\n/ insert a unique marker (\n)
ta;:a jump to a loop label (resets the substitute true/false flag)
s/\n$//;t if marker at the end of the line, remove and bail out
s/\n\(\(“[^”]*”\)\|\(‘\”[^’\”]*’\”\)\)/\1\n/;ta if the string following the marker is a quoted one, bump the marker forward of it and loop.
s/\n\([^#]\)/\1\n/;ta if the character following the marker is not a #, bump the marker forward of it and loop.


  1. Shamelessly plagiarized from

Comment whole section from ini file

Instead of using the ansible ini_file state=absent section=”Zabbix”, you can use this instead, to comment out the section. I realize you can just do a backup=yes option, but for the quick cases where you don’t want to fire up ansible:

tmpfile1=$( mktemp ); sed -r -e '/^\[/i#ENGLISH877' ~/foo | sed -r -e '/^\[Zabbix\]/,/ENGLISH877/s/^/#/;' | sed -r -e '/#ENGLISH877/d' > ${tmpfile1}; cat ${tmpfile1} > ~/foo


The first sed statement inserts a new line with content “#ENGLISH877” (random string that will be unlikely to cause collisions) right before the start of each new section.
The second sed statement then modifies the section specified (“Zabbix”) and inserts comments at the beginning.
The last sed removes all instances of the random string we inserted.

Bash one liner: remove extra slashes from file path

If you have a generated path, you might end up with extra slashes, such as


In a typical Linux file system such as ext2, ext3, or ext4, /mnt/foo//bar is the same file as /mnt/foo/bar. The slashes two in a row are the same as a /./, and a single dot is the same directory. So /mnt/. is directory /mnt/ — that’s just how they made the filesystem.
The notable exception is at the beginning of a path, where //servername would actually be a reference to the network host servername. I leave it as an exercise to the reader to know when he is parsing network paths and when he is not.

You can clean duped slashes easily by doing this:

file="$( file | sed -e 's!\/\+!\/!g;' )"

Replace config file entry or append if not found

Suppose you need to replace whatever current setting for a particular application to a specific setting. It doesn’t matter what it was before, or if it was absent. You want to define it.

Suppose you want to replace the session pam_mkhomedir setting in /etc/pam.d/common-session to be required. If it was optional, replace it. If it wasn’t listed at all, add it. This line updates an answer on stackoverflow.

sed -i -e '\|session.*|h; ${x;s/mkhomedir//;{g;tF};a\' -e 'session\trequired\ umask=0022' -e '};:F;s/.*mkhomedir.*/session\trequired\ umask=0022/g;' /etc/pam.d/common-session

The -i makes the change inline directly in the file. I write deployment scripts so I don’t care about displaying the output; I want to change the original.

Basically the command looks like this:

sed -e '\|variable.*(possible|values|go|hereornot)|h; ${x;s/variable//;{g;tF};a\' -e 'variable updatedvalue1 updatedvalue2' -e '};:F;s/.*variable.*/variable thisvalueadded1/g;' /etc/inputfile

Questions? I would be happy to explain this if you want a guided tour.