É mais fácil de fazer com perl
:
perl -0777 -pi -e 's{/\*.*?\*/}{/* new comment */}s' file.c
Substituiria a primeira ocorrência de /*...*/
pelo novo comentário.
sed
processa o texto uma linha por vez, portanto você não pode corresponder a um texto com várias linhas, a menos que adicione as outras linhas ao espaço do padrão (ou use -z
com versões recentes do GUN sed
):
sed -zi 's|/\*.*\*/|/* new comment */|' file.c
Ou portável (assumindo arquivos curtos):
sed -e :1 -e '$!{N;b1' -e '}' -e 's|/\*.*\*/|/* new comment */|' file.c
No entanto, observe que, como sed
não suporta o operador *?
non-greedy de perl
, isso significa que ele corresponderá da primeira ocorrência de /*
ao último ocorrência de */
, então substituiria /* comment 1 */ some C code /* comment 2 */
por /* new comment */
.
Fazê-lo com sed
é possível, mas mais doloroso. Veja aqui para um exemplo (que também cuida de evitar /*
ocorrências dentro de "strings"
e algumas outras advertências).
Uma solução simplificada que seria equivalente a perl
one seria algo como:
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
Com o GNU awk
, você poderia fazer:
awk -v RS='\*/' '
!found && sub(/\/\*.*/, "/* new comment ") {found = 1}
{printf "%s", $0 RT}' file.c