The easiest way to remove comments from a shell script is to use sed (stream editor for filtering and transforming text) command.
An updated source code is available at GitHub.
Let’s prepare a sample shell 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 the following 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 let’s write sed commands in a 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:
Always print the first line if it defines an interpreter
Remove “empty” lines with comments
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 an 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