shantanuo
shantanuo

Reputation: 32316

Remove multi-line comments

How do I remove all comments if they start with /* and end with */ I have tried the following. It works for one line comment.

sed '/\/\*/d' 

But it does not remove multiline comments. for e.g. the second and third lines are not removed.

/*!50500 PARTITION BY RANGE (TO_SECONDS(date_time ))
 PARTITION 20120102parti VALUES LESS THAN (63492681600),
(PARTITION 20120101parti VALUES LESS THAN (63492595200) */ ;

In the above example, I need to retain the last ; after the closing comment sign.

Upvotes: 12

Views: 24996

Answers (7)

Ed Morton
Ed Morton

Reputation: 203532

If this is in a C file then you MUST use a C preprocessor for this in combination with other tools to temporarily disable specific preprocessor functionality like expanding #defines or #includes, all other approaches will fail in edge cases. This will work for all cases:

[ $# -eq 2 ] && arg="$1" || arg=""
eval file="\$$#"
sed 's/a/aA/g; s/__/aB/g; s/#/aC/g' "$file" |
          gcc -P -E $arg - |
          sed 's/aC/#/g; s/aB/__/g; s/aA/a/g'

Put it in a shell script and call it with the name of the file you want parsed, optionally prefixed by a flag like "-ansi" to specify the C standard to apply.

See https://stackoverflow.com/a/35708616/1745001 for details.

Upvotes: 13

vbence
vbence

Reputation: 20333

A sed-only solution:

sed -r 's/\/\*(.*?)\*\///g' \
    | sed -r 's/(.+)(\/\*)/\1\n\2/g'\
    | sed -r 's/(\*\/)(.+)/\1\n\2/g' \
    | sed '/\/\*/,/\*\// s/.*//'

Shortcomings: multi-line comments will leave empty lines (because sed is line-based, unless you put in superhuman efforts).

Explanation

  • s/\/\*(.*?)\*\///g will take care of single-line comments.
  • s/(.+)(\/\*)/\1\n\2/g and s/(\*\/)(.+)/\1\n\2/g will split lines at the beginning and end of multi-line comments.
  • /\/\*/,/\*\// s/.*// will run the command s/.*// effectively deleting all the lines between the patterns \/\* and \*\/ - which is /* and */ escaped.

Upvotes: 1

Constantine Gladky
Constantine Gladky

Reputation: 1263

Try this

sed "/^\//,/\/;/d" filename

Upvotes: -1

GregV
GregV

Reputation: 2525

To complement Ed's answer (focused on C files), I would suggest the excellent sed script remccoms3.sed by Brian Hiles for non-C files (e.g. PL/SQL file). It handles C and C++ (//) comments and correctly skips comments inside strings. The script is available here: http://sed.sourceforge.net/grabbag/scripts/remccoms3.sed

Upvotes: 2

potong
potong

Reputation: 58420

This might work for you (GNU sed):

sed -r ':a;$!{N;ba};s|/\*[^*]*\*+([^/*][^*]*\*+)*/||' file

It's a start, anyway!

Upvotes: 3

Steve
Steve

Reputation: 54402

Here's one way using GNU sed. Run like sed -rf script.sed file.txt

Contents of script.sed:

:a
s%(.*)/\*.*\*/%\1%
ta
/\/\*/ !b
N
ba

Alternatively, here's the one liner:

sed -r ':a; s%(.*)/\*.*\*/%\1%; ta; /\/\*/ !b; N; ba' file.txt

Upvotes: 18

Anshu
Anshu

Reputation: 7853

This should do

 sed 's|/\*|\n&|g;s|*/|&\n|g' a.txt | sed '/\/\*/,/*\//d'

For test:

a.txt

/* Line test
multi
comment */
Hello there
this would stay 
/* this would be deleteed */

Command:

$ sed 's|/\*|\n&|g;s|*/|&\n|g' a.txt | sed '/\/\*/,/*\//d'
Hello there
this would stay 

Upvotes: 9

Related Questions