2

Assume that I have a file that starts with the following

    /*********************************************************
    blah blah blah
    blah blah blah
    blah blah blah
    *********************************************************/
    Actual code follows here
    code 
    code 
    code

The command I used:

    sed -i 's/(/*).*(*/)/\1 newcomment \2/1' file

but I received the error message

    sed: -e expression #1, char 14: unknown option to `s'

p.s. my question is ... how can i REPLACE the "blah blah blah..." comments with other bloah bloah bloah comments ?

Chan
  • 23
  • 1
  • 5

2 Answers2

2

It's more easily done with perl:

perl -0777 -pi -e 's{/\*.*?\*/}{/* new comment */}s' file.c

Would replace the first occurrence of /*...*/ with the new comment.

sed processes the text one line at a time, so you can't match a multi-line text, unless you do add the other lines to the pattern space (or you use -z with recent versions of GUN sed):

sed -zi 's|/\*.*\*/|/* new comment */|' file.c

Or portably (assuming short files):

sed -e :1 -e '$!{N;b1' -e '}' -e 's|/\*.*\*/|/* new comment */|' file.c

However note that since sed doesn't support the *? non-greedy operator of perl, that means that it will match from the first occurrence of /* to the last occurrence of */, so it would replace /* comment 1 */ some C code /* comment 2 */ with /* new comment */.

Doing it with sed is possible but more painful. See here for an example (that also takes care of avoiding /* occurrences inside "strings" and a few other caveats).

A simplified solution that would be the equivalent of that perl one would be something like:

sed '
  # load the whole file into the pattern space
  :1
  $!{
    N;b1
  }
  s/_/_u/g;s/>/_c/g; # use _ as an escape character to escape
                     # the > we will be using in place of */
  s|\*/|>|g; # replace */ with >
  s|/\*[^>]*>|/* new comment */|
  s|>|*/|g; # undo the replacement and escaping
  s/>/_c/g;s/_u/_/g' file.c

With GNU awk, you could do:

awk -v RS='\\*/' '
  !found && sub(/\/\*.*/, "/* new comment ") {found = 1}
  {printf "%s", $0 RT}' file.c
Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
  • i think ur answer might be more correct but I don't use perl so, can u you think of a way to use SED or AWK ... the previous answer provided for SED actually DOES NOT REPLACE THE OLD COMMENT .... MERELY ADDS THE NEW COMMENT –  Chan Aug 18 '16 at 09:16
  • wow so, genuinely it would mean that I cannot control whether this is the first comment only ? Assuming there are multiple comments in the c code file .... and I just want to REPLACE THE FIRST COMMENT WHICH STRETECHES OVER MULTIPLE LINES ..... what do I do with sed ? –  Chan Aug 18 '16 at 09:30
  • @Chan, see edit. – Stéphane Chazelas Aug 18 '16 at 09:34
  • @stepahne can u please recommend me some source to educate myself. this code is rather long and confusing for a newbie like myself. I thoroughly appreciate it. One final remark , regarding to the simplified Perl version. how do I store a temp original file and make the difference between files visible aka printable using diff –  Chan Aug 18 '16 at 09:41
  • final question. how do i include multi line comment as newcomment ? if i am using the perl function are there any abbreviations ? –  Chan Aug 18 '16 at 10:11
1

Escape the brackets and slashes

 sed -i 's/\(\/*\).*\(*\/\)/\1 newcomment \2/1' file
Ipor Sircer
  • 14,376
  • 1
  • 27
  • 34