Como pesquisar e substituir múltiplas agulhas por uma palavra através de uma expressão?

8

Suponha que você tenha um arquivo de texto:

foo fnord bar
bizz foo poit

E agora eu gostaria de substituir "foo" e "bar" em "narf".

Eu sei que posso usar:

 sed -e 's/foo/narf/g' -e 's/bar/narf/g' fileName

No entanto, gostaria de trabalhar com um operador OR que diga ao regex para combinar as duas agulhas por meio de uma expressão.

Acertando alguns manuais, suponho que o pipe deve atender às minhas necessidades, mas tentei

sed -e 's/foo|bar/narf/g' -i fileName

e não funcionou e nem sequer está a gerar um erro.

O que estou fazendo de errado aqui?

    
por k0pernikus 24.11.2011 / 23:26

3 respostas

10

Use a opção -r para sintaxe estendida de regexp:

sed -r -e 's/foo|bar/narf/g'

Caso contrário, escape da disjunção como \| :

sed -e 's/foo\|bar/narf/g'
    
por 24.11.2011 / 23:48
6

Existem muitas variações na sintaxe expressão regular . As primeiras ferramentas no mundo unix que tinham expressões regulares não tinham todos os recursos de expressões regulares, apenas conjuntos de caracteres ( […] e . ), repetição ( * ) e âncoras de linha ( ^ e% código%). Expressões regulares básicas só têm esses operadores. Sed é uma ferramenta antiga e usa regexps básicos.

Muitas implementações de sed têm extensões para correspondência completa de regexp. Como o caractere $ significa ele mesmo, você precisa usar | para alternação e, da mesma forma, \| e \( para agrupamento. Note que o padrão POSIX não exige que \) seja suportado em expressões regulares básicas e alguns sistemas (por exemplo, OpenBSD ) não tem isso.

Algumas versões do sed têm a opção de alternar para expressões regulares estendidas , em que \| é usado para agrupamento e (…) para alternação. Com o GNU sed (por exemplo, no Linux ou no Cygwin) ou no Busybox , passe a opção | . Em FreeBSD ou OSX , passe a opção -r .

Se o seu sed não tiver alternância, você pode chamar -E . Ele é obrigatório por POSIX , mas um pouco detalhado para essa tarefa, e não suporta referências anteriores.

awk '{gsub(/foo|bar/, "narf")}' <fileName.old >fileName.new

A propósito, somente o GNU e o Busybox sed suportam a substituição de arquivos no lugar. Awk e outras versões do sed não. Veja Posso fazer 'cortar' alterar um arquivo no lugar

Se você tem Perl, muitas vezes é útil em um one-tool-does-all-way para processamento de texto one-liners. A maior parte do que é fácil em sed, awk e o resto não é muito mais difícil em Perl, e você pode aprender uma única ferramenta (se complexa).

perl -i -pe 's/foo|bar/narf/g' fileName
    
por 25.11.2011 / 00:14
0

Você pode usar o Vim no modo Ex:

ex -sc '%s/\vPA|QU/RO/g|x' file
  1. % seleciona todas as linhas

  2. s substituto

  3. \v ativa a mágica

  4. g global replace

  5. x salvar e fechar

por 17.04.2016 / 06:42