Substituir texto entre parênteses

2

Estou usando awk '{ gsub(/BAR|WIBBLE/, "FOO"); print }' para substituir texto em dados como:

SOMETHING [BAR, WIBBLE]
SOMETHING [BAR]

Isso dá o resultado desejado de:

SOMETHING [FOO, FOO]
SOMETHING [FOO]

Mas agora eu tive que atualizar o texto que requer substituição para ser algo como:

awk '{ gsub(/BAR|WIBBLE|ME/, "FOO"); print }'

Que transforma texto como:

SOMETHING [ME, WIBBLE]

para:

SOFOOTHING [FOO, FOO]

Como posso limitar minha substituição apenas ao texto entre colchetes (ou seja, deixar o SOMETHING sozinho)?

EDITAR

Também preciso de robustez em qualquer texto SOMETHING (por exemplo, SHE GAVE ME THAT não deveria ter ME substituído).

    
por Chris 24.10.2012 / 18:10

4 respostas

5

Deve ser awk ? É muito mais fácil em outros idiomas onde a peça de substituição da substituição pode ser uma chamada de função. Por exemplo perl :

perl -pe 'sub c{$s=shift;$s=~s/BAR|WIBBLE|ME/FOO/g;$s}s/\[.*?\]/c$&/ge' 
    
por 24.10.2012 / 18:15
3

Com o GNU awk, você pode definir RS para o conteúdo dos colchetes e, em seguida, fazer a substituição no RT (separador de registros correspondente):

awk -v RS='\[[^]]*\]' '{ gsub(/\<(BAR|WIBBLE|ME)\>/, "FOO", RT); printf "%s%s", $0, RT }' infile

infile:

cat << EOF > infile
SHE GAVE ME THAT
SOMETHING [ME, WIBBLE, SOMMER]
EOF

saída:

SHE GAVE ME THAT
SOMETHING [FOO, FOO, SOMMER]
    
por 25.10.2012 / 10:56
2

O awk não tem referências anteriores nas substituições de expressões regulares, por isso não é fácil fazer substituições no contexto. Sed pode fazer isso:

sed -e 's/\(\[[^]]*\)BAR/FOO/' 's/\(\[[^]]*\)ME/FOO/'

Se o seu sed suportar alternações em regexps:

sed -e 's/\(\[[^]]*\)\(BAR\|ME\)/FOO/'

Isso lida apenas com uma única substituição dentro de cada par de colchetes, mesmo com o sufixo g , porque [^]]* corresponde à sequência mais longa sem parentesco. Para substituir todos eles, use um loop explícito; Observe que isso só funciona se FOO não for uma subseqüência de BAR ou ME .

sed -e ': a' -e 's/\(\[[^]]*\)BAR/FOO/' -e 't a' \
             -e 's/\(\[[^]]*\)ME/FOO/' -e 't a'

Se você precisar de algo mais complicado, use perl .

    
por 25.10.2012 / 02:12
-3
awk '{ gsub(/\bBAR\b|\bWIBBLE\b|\bME\b/, "FOO"); print }'
    
por 24.10.2012 / 18:16