3

How do I remove multi-line C style comments like:

/* comments
   comments
   comments
   comments */

I am able to remove comments in one line like /* comments */ by using several codes provided in other questions.

s#/\*[\s\S]*?\*/##sg;
s#/\*(.*?)\*/##sg;
s#/\*[^*]*\*+([^/*][^*]*\*+)*/|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^/"'\\]*)#defined $2 ? $2 : ""#gse

All three regexes above do not work with multi-line comments. How can they be handled?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
double_espresso
  • 115
  • 2
  • 12
  • 1
    Do you need to deal with bastardiferous C comments like ``/\`` on one line, ``\`` on the next, and ``* comment *\`` on the next, another line with just ``\``, and finally `/` on the next line, marking the end of comment? Do you need to allow for any of those backslashes to be written `??/` instead of ``\``? – Jonathan Leffler Dec 29 '14 at 01:32
  • I managed to remove one line comments like `// something`. However, I'm not very sure about the backslashes you mentioned, sorry, coding newbie here ;) – double_espresso Dec 29 '14 at 01:40
  • Good. Does that also handle multi-line ``// something\`` lines with `continuation of previous comment` on the next line? If you're a newbie at this, you can decide that the bastardiferous comments are out of scope, not least because anyone actually writing them deserves to be hung, drawn, and quartered for abuse of C (or C++, or Java, or whatever language it really is). Nevertheless, that's the sort of nonsense that compiler writers have to deal with. – Jonathan Leffler Dec 29 '14 at 01:41
  • @AvinashRaj: well, for one thing, comments can start at the end of one line and continue onto subsequent lines. Also, at some point, you have to worry about: `const char c_start[] = "/*"; const char c_end[] = "*/";` which does not contain any comment. You can even have non-portable code like `int c1 = '/*'; int c2 = '*/';` which also doesn't contain any comments. Doing this job thoroughly is decidedly non-trivial. However, this sort of stuff may well be beyond what the OP needs to handle, and he can thank his lucky stars he's not producing a commercial-grade comment remover. – Jonathan Leffler Dec 29 '14 at 01:46
  • I see what you meant earlier. I don't need to handle those comments. My task only contains multi line `/*something*/` and `//something`. – double_espresso Dec 29 '14 at 01:47
  • 1
    Tha answer is in the FAQ: http://perldoc.perl.org/perlfaq6.html#How-do-I-use-a-regular-expression-to-strip-C-style-comments-from-a-file? – Toto Dec 30 '14 at 10:12

1 Answers1

5

I would do like,

perl -0777pe 's/\/\*(?:(?!\*\/).)*\*\/\n?//sg' file

Example:

$ cat fi
/* comments
   comments
   comments
   comments */
bar
$ perl -0777pe 's/\/\*(?:(?!\*\/).)*\*\/\n?//sg' fi
bar
Avinash Raj
  • 172,303
  • 28
  • 230
  • 274
  • The one-liner works if I type it in the command window. However, I'm supposed to open a text file and remove comments in it. `s/\/\*(?:(?!\*\/).)*\*\/\n?//sg foreach (@lines)` removes single line comments but not multi-line comments. Any ideas? – double_espresso Dec 29 '14 at 01:55
  • i think foreach loop would fetch only a single line at a time. – Avinash Raj Dec 29 '14 at 01:58
  • Why are you using paragraph mode `-00`? Did you mean to use slurp mode `-0777`? – TLP Dec 29 '14 at 02:02
  • ya, `00pe` won't work if there is a blank line in-between `/*` and `*/` – Avinash Raj Dec 29 '14 at 02:04
  • Now i see that where my problems at! Is there any way to check the file line by line while removing comments without using foreach/for? – double_espresso Dec 29 '14 at 02:09
  • just read the entire file into a string and do the replacement on that string. http://stackoverflow.com/questions/953707/in-perl-how-can-i-read-an-entire-file-into-a-string – Avinash Raj Dec 29 '14 at 02:47