How to remove comments from a shell script

The easiest way to remove comments from a shell script is to use sed (stream editor for filtering and transforming text) command. I will write down one and useful way to achieve this goal but keep in mind that I am not sed expert by any means so always backup your work.

Updated source code is available at GitHub.

Lets prepare example script for testing purposes:

$ cat example.sh 
#!/bin/bash
# example script

echo "# test";# echo "# test"

# check the first parameter
if [ "$1" = "#" ]; then 
  # test couple of different cases
  echo "#"; # output # character 
  echo '\#'; # output # character '#' for test purpose
  echo \#\#\#; # comment # comment # comment '# comment'
  echo \#
  echo \#;
  echo \#; # comment
fi
# end of the script

To remove comments execute command:

sed -e '1{/^#!/ {p}}; /^[\t\ ]*#/d;/\.*#.*/ {/[\x22\x27].*#.*[\x22\x27]/ !{:regular_loop s/\(.*\)*[^\]#.*/\1/;t regular_loop}; /[\x22\x27].*#.*[\x22\x27]/ {:special_loop s/\([\x22\x27].*#.*[^\x22\x27]\)#.*/\1/;t special_loop}; /\\#/ {:second_special_loop s/\(.*\\#.*[^\]\)#.*/\1/;t second_special_loop}}' example.sh
#!/bin/bash

echo "# test";

if [ "$1" = "#" ]; then 
  echo "#"; 
  echo '\#'; 
  echo \#\#\#; 
  echo \#
  echo \#;
  echo \#;
fi

It looks complicated so lets store sed commands in more readable way:

$ cat remove_comments.sed
1 {
  /^#!/ {
    p
  }
}

/^[\t\ ]*#/d

/\.*#.*/ {
  /[\x22\x27].*#.*[\x22\x27]/ !{
    :regular_loop
      s/\(.*\)*[^\]#.*/\1/
    t regular_loop
  }
  /[\x22\x27].*#.*[\x22\x27]/ {
    :special_loop
      s/\([\x22\x27].*#.*[^\x22\x27]\)#.*/\1/
    t special_loop
  }
  /\\#/ {
    :second_special_loop
      s/\(.*\\#.*[^\]\)#.*/\1/
    t second_special_loop
  }
}

Very short description:
1. Always print the first line if it defines an interpreter
2. Remove "empty" lines with comments
3. Parse comments
3.1 Remove comments from lines without ' or " characters
3.2 Remove comments from lines with ' or " characters
3.3 Remove comments from lines with escaped # character

Now you can easily check any applied changes:

$ sed -f remove_comments.sed example.sh 
#!/bin/bash

echo "# test";

if [ "$1" = "#" ]; then 
  echo "#"; 
  echo '\#'; 
  echo \#\#\#; 
  echo \#
  echo \#;
  echo \#;
fi

Check out file differences:

$ sed -f remove_comments.sed example.sh | diff -u example.sh -
--- example.sh  2012-11-07 00:42:00.876279927 +0100
+++ -   2012-11-07 00:44:03.340909374 +0100
@@ -1,16 +1,12 @@
 #!/bin/bash
-# example script
 
-echo "# test";# echo "# test"
+echo "# test";
 
-# check the first parameter
 if [ "$1" = "#" ]; then 
-  # test couple of different cases
-  echo "#"; # output # character 
-  echo '\#'; # output # character '#' for test purpose
-  echo \#\#\#; # comment # comment # comment '# comment'
+  echo "#"; 
+  echo '\#'; 
+  echo \#\#\#; 
   echo \#
   echo \#;
-  echo \#; # comment
+  echo \#;
 fi
-# end of the script

Remove comments from a file and store backup with .backup suffix:

$ sed -i.backup -f remove_comments.sed example.sh 
Milosz Galazka's Picture

About Milosz Galazka

Milosz is a Linux Foundation Certified Engineer working for a successful Polish company as a system administrator and a long time supporter of Free Software Foundation and Debian operating system.

Gdansk, Poland https://sleeplessbeastie.eu