É assim que se faz uma correspondência não gananciosa de seqüências de caracteres múltiplos usando sed. Digamos que você queira alterar todos os itens foo...bar
para <foo...bar>
, por exemplo, esta entrada:
$ cat file
ABC foo DEF bar GHI foo KLM bar NOP foo QRS bar TUV
deve se tornar esta saída:
ABC <foo DEF bar> GHI <foo KLM bar> NOP <foo QRS bar> TUV
Para fazer isso, você converte foo e barra em caracteres individuais e, em seguida, use a negação desses caracteres entre eles:
$ sed 's/@/@A/g; s/{/@B/g; s/}/@C/g; s/foo/{/g; s/bar/}/g; s/{[^{}]*}/<&>/g; s/}/bar/g; s/{/foo/g; s/@C/}/g; s/@B/{/g; s/@A/@/g' file
ABC <foo DEF bar> GHI <foo KLM bar> NOP <foo QRS bar> TUV
No exemplo acima:
s/@/@A/g; s/{/@B/g; s/}/@C/g
está convertendo {
e }
em seqüências de espaço reservado que não podem existir na entrada, para que esses caracteres estejam disponíveis para conversão foo
ebar
para.
s/foo/{/g; s/bar/}/g
está convertendo foo
e bar
para {
e}
respectivamente
s/{[^{}]*}/<&>/g
está realizando a operação que queremos - convertendo foo...bar
para<foo...bar>
s/}/bar/g; s/{/foo/g
está convertendo {
e de }
volta para foo
ebar
.
s/@C/}/g; s/@B/{/g; s/@A/@/g
está convertendo as seqüências de caracteres do espaço reservado em seus caracteres originais.
Observe que o acima exposto não depende de nenhuma string em particular não estar presente na entrada, pois ela fabrica essas strings na primeira etapa, nem se importa com a ocorrência de qualquer regexp em particular que você deseja corresponder, pois você pode usar {[^{}]*}
quantas vezes for necessário. na expressão para isolar a correspondência real desejada e / ou com o operador de correspondência numérica seds, por exemplo, para substituir apenas a 2ª ocorrência:
$ sed 's/@/@A/g; s/{/@B/g; s/}/@C/g; s/foo/{/g; s/bar/}/g; s/{[^{}]*}/<&>/2; s/}/bar/g; s/{/foo/g; s/@C/}/g; s/@B/{/g; s/@A/@/g' file
ABC foo DEF bar GHI <foo KLM bar> NOP foo QRS bar TUV