10

I am trying to write a script that will delete all comments and everything in between inside C files in my current directory. I've been using sed, and this is what I have so far:

sed -i '/ * [^()] */d' *.c

This works when the comments are on the same line as an asterisk or backslash.

However it doesn't work when there is a commented line without a slash or asterisk.

I know sed goes line by line, I just don't know how to tell it to keep deleting until it sees a */.

jasonwryan
  • 71,734
  • 34
  • 193
  • 226
Dawn
  • 101
  • 1
  • 3
  • Depending on what your are trying to accomplish, one possible solution to remove comments could be to run only the preprocessing step of the compilation. e.g., `gcc -E test.c > test_p.c`. This will however include header files in the C-file. Otherwise I think you are better of with some kind of utility that is capable of parsing C-files, such as some kind of beautifier. – Kotte Apr 15 '13 at 16:03
  • See also: [How can I delete all characters falling under /* … */](http://unix.stackexchange.com/q/297346) – don_crissti Oct 20 '16 at 21:34

2 Answers2

9

Removing comments without using a real C-preprocessor is not exactly trivial. I once came up with something like this:

perl -0777 -pe'
 s{
     /\*.*?\*/
   | //[^\n]*
   | (
        "(?:\\.|.)*?"
      | '\''(?:\\.)?.*?'\''
      | \?\?'\''
      | .[^'\''"/]*
     )
  }{if ($1eq""){" "}else{$1}}exsg' 

Which should cover most cases like things like:

printf("%c%c%s", '"' /* d-quote */, '\'', "/*" "*/");

See the interesting discussion there for more details.

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
4

If this doesn't have to be done in sed, then you can do it easily with perl:

perl -p0i -e 's#/\*.*?\*/##sg' *.c

Note that this will delete parts of quoted strings that are not meant to be comments at all as in the example in the comments below.

Joseph R.
  • 38,849
  • 7
  • 107
  • 143
  • 3
    This fails pretty spectacularly. Try this: `echo 'printf("Comments in C are written /* like this */.\n");' | perl -p0i -e 's#/\*.*?\*/##sg'` – user Apr 15 '13 at 13:59
  • Good point. This code does not make provisions for the case when block comments occur inside quoted text. Editing answer. – Joseph R. Apr 15 '13 at 15:39
  • I voted your answer, although it does not cover twisted cases. using the non-greedy regex .*? is a smart trick and does the job trick for 90% of cases – Muayyad Alsadi Apr 15 '13 at 18:15