Como localizar e substituir a string sem usar o comando Sed?

11

Como todos sabemos, sed é muito eficiente para encontrar e substituir string, por exemplo, encontrar 'a' e substitua por 'b': sed 's/a/b/g' .

É possível fazer isso com outro comando ou script de shell em vez de sed ?

Isto é para um sistema linux cortado para TV que não possui o comando sed . Então eu tenho que usar outros comandos ou scripts em vez de sed 's/a/b/g'. –

    
por binghenzq 25.10.2013 / 17:19

5 respostas

8

Sim, há várias maneiras de fazer isso. Você também pode usar awk , perl ou bash para realizar essas atividades. Em geral, embora sed seja provavelmente a ferramenta mais apropriada para realizar esses tipos de tarefas.

Exemplos

Digamos que eu tenha esses dados de amostra, em um arquivo data.txt :

foo bar 12,300.50
foo bar 2,300.50
abc xyz 1,22,300.50

awk

$ awk '{gsub("foo", "foofoofoo", $0); print}' data.txt 
foofoofoo bar 12,300.50
foofoofoo bar 2,300.50
abc xyz 1,22,300.50

Perl

$ perl -pe "s/foo/foofoofoo/g" data.txt 
foofoofoo bar 12,300.50
foofoofoo bar 2,300.50
abc xyz 1,22,300.50

Edição in-line

Os exemplos acima podem modificar diretamente os arquivos também. O exemplo do Perl é trivial. Basta adicionar a opção -i .

$ perl -pie "s/foo/foofoofoo/g" data.txt 

Para awk , é um pouco menos direta, mas igualmente eficaz:

$ { rm data.txt && awk '{gsub("foo", "foofoofoo", $0); print}' > data.txt; } < data.txt

Este método cria um sub-shell com as chaves '{...}' onde o arquivo é redirecionado para ele via isso:

$ { ... } < data.txt

Depois que o arquivo for redirecionado para o sub-shell, ele é excluído e, em seguida, awk é executado no conteúdo do arquivo que foi lido nas sub-shells STDIN. Este conteúdo é então processado por awk e escrito de volta para o mesmo nome de arquivo que acabamos de excluir, efetivamente substituindo-o.

    
por 25.10.2013 / 17:35
12

A alternativa clássica para substituições de letras únicas é o comando tr que deve estar disponível em praticamente qualquer sistema:

$ echo "foobar" | tr a b   
foobbr

tr é melhor que sed para isso, já que usar sed (sem falar em perl ou awk ) para substituições de letras únicas é como usar um martelo para matar uma mosca.

grep não é projetado para isso, ele não modifica sua entrada, apenas procura por ele.

Como alternativa, você pode usar os recursos de substituição de alguns shells. Aqui, usando a sintaxe ksh , zsh ou bash :

$ foo="foobar"
$ echo "${foo//a/b}"
foobbr

Poderíamos lhe dar respostas mais específicas se você explicasse exatamente o problema que está tentando resolver.

    
por 25.10.2013 / 18:53
4

Você pode usar o Vim no modo Ex:

ex -s -c '%s/a/b/g|x' file
  1. % seleciona todas as linhas

  2. s substituto

  3. g global replace

  4. x salvar e fechar

por 17.04.2016 / 08:16
2

Se você estiver trabalhando com um arquivo em vez de um fluxo, poderá usar o editor de texto padrão, ed :

printf '%s\n' ',s/a/b/g' w q | ed file.txt

Isso deve estar disponível em qualquer * nix. A vírgula em ',s/a/b/g' diz a ed para trabalhar na linha every (você também pode usar % , que será mais familiar se estiver habituado ao vim), e o resto dela é uma pesquisa e substituição padrão. w diz para escrever (salvar) o arquivo, q diz para sair.

Note que, ao contrário da opção -i do sed (e opções similares em outras ferramentas), isso na verdade edita o arquivo no local em vez de trapacear com arquivos temporários.

Eu não acho que é possível fazer isso funcionar com streams, mas eu realmente não sei muito sobre ed e eu não ficaria surpreso se realmente tivesse essa capacidade (a filosofia unix sendo o que é).

    
por 25.10.2013 / 20:46
1

Usando o comando (em que -s significa silêncio (silencioso) e a vírgula antes dos comandos significa executar em todas as linhas):

Basta imprimir em STDOUT :

ed -s file <<!
,s/a/b/g
,p
q
!

substituindo no local:

ed -s file <<!
,s/a/b/g
w
q
!
    
por 25.10.2013 / 21:15