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.