O problema com um
sed -i 's/foo\(.*\)foo/hatcar/g'
A abordagem é que ela alteraria fooxfoo fooyfoo
para hatxfoo fooycar
, pois .*
é ganancioso.
Você pode usar perl
com seu operador .*?
não-ganancioso.
perl -i -pe 's/foo(.*?)foo/hat$1car/g'
(que também tem a vantagem de ser mais portátil. Esse -i
vem de perl
e não está disponível em muitas implementações de sed
(e quando é, não é interpretado da mesma forma por todos)). / p>
Com o GNU sed
e desde que o $POSIXLY_CORRECT
não esteja no ambiente, você poderia fazer:
sed -i 's/foo/\n/g;s/\n\([^\n]*\)\n/hatcar/g;s/\n/foo/g'
Ou seja, substitua foo
por um caractere ( \n
, o delimitador de linha) que não pode ocorrer na linha, para que possamos usar [^\n]*
para obter o equivalente não-ganancioso.
Se POSIXLY_CORRECT estiver no ambiente, [^\n]
corresponderia a qualquer caractere, mas \
e n
, como POSIX requer, em vez de qualquer caractere, exceto nova linha. Você sempre pode fazer:
(unset -v POSIXLY_CORRECT; exec sed...)
se você quiser que seu script ainda funcione em ambientes em que POSIXLY_CORRECT esteja definido.