Como encontrar e substituir string sem usar o comando Sed?

Como todos sabemos, sed é muito eficiente para localizar e substituir strings, por exemplo, encontre “a” e substitua-o por “b”: sed "s/a/b/g".

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

Isso é para sistemas linux cortados para TV que não tem o comando sed. Portanto, tenho que usar outros comandos ou scripts em vez de sed "s/a/b/g". –

Comentários

  • Na verdade, isto é apenas substituição baseada em expressão regular. Qualquer ferramenta ou linguagem capaz de lidar com isso poderá fazer o mesmo, mas com várias sintaxes: $var=~s/a/b/g, gsub(/a/,"b",var), var.gsub(/a/,'b'), var.replace(/a/g,'b'), preg_replace("/a/","b",$var), regsub -all a b $var. Além disso, muitas ferramentas e linguagens também podem fazer a substituição de strings de texto simples. Portanto, sua pergunta é de alguma forma ampla.
  • Por quê? Que problema você está tentando resolver?
  • Um sistema linux cortado para TV não tem o comando sed. Portanto, preciso usar outro comando ou script em vez de sed ‘ s / a / b / g ‘.

Resposta

Sim, há uma variedade de maneiras de fazer isso. Você pode usar awk, perl ou bash para fazer essas atividades também. Em geral, embora sed seja provavelmente a ferramenta mais apropriada para fazer 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 inline

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

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

Para awk isso “um pouco menos direto, 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 está redirecionado para ele por meio deste:

$ { ... } < data.txt 

Assim 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 nos sub-shells STDIN. Esse conteúdo é então processado por awk e gravado de volta no mesmo nome de arquivo que acabamos de excluir, substituindo-o efetivamente.

Comentários

  • Obrigado por responder e tentarei no próximo dia de trabalho. Mas não tenho certeza se funciona porque algum comando pode não existir em sistemas linux cortados de TV, como ‘ sed ‘. Então, eu ainda quero usar comando ‘ find ‘, ‘ grep ‘ e assim por diante para resolvê-lo.
  • @binghenzq – Eu ‘ adicionei exemplos que editam in-line o arquivo.
  • -1 Raramente voto negativo, mas neste caso o ponto de a pergunta parecia ser um método mais simples do que outro mais / igualmente complexo e provavelmente também dependente. Se a pergunta fosse apenas sobre alternativas para uma instalação completa da máquina * nix, eu provavelmente adicionaria esta resposta com +1.
  • @MichaelDurrant – acabei de adicionar essas edições inline elaboradas b / c o OP pediu para elas . Além disso, o OP define o requisito de NÃO usando sed não I. Sed é a ferramenta apropriada para fazer substituições como esta, e ele ‘ s obviamente pedindo para entender melhor as funções dessas ferramentas, portanto, mostrar a alguém essas coisas, embora ruins, é extremamente educativo para mostrar o porquê. Muitas vezes a pessoa sabe simplesmente dizer ” não ‘ t faça isso ” sem explicar o porquê, estou. Mas obrigado por, pelo menos, deixar um comentário sobre o motivo pelo qual você DV.
  • Claro, eu achei uma ótima resposta em todos os outros aspectos. sim, eu odeio -1 sem explicação.

Resposta

A alternativa clássica para substituições de uma única letra é a tr comando que deve estar disponível em praticamente qualquer sistema:

$ echo "foobar" | tr a b foobbr 

tr é melhor do que sed para isso, na verdade, desde o uso de sed (quanto mais perl ou awk) para substituições de uma única letra é como usar uma marreta para matar uma mosca.

grep não foi projetado para isso, ele não modifica sua entrada, apenas pesquisa através dela.

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

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

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

Comentários

  • Existe uma opção para ignorar maiúsculas e minúsculas em ${foo//a/b}?
  • @ AlikElzin-kilaka I ‘ estou com medo não. Você ‘ terá que usar algo mais sofisticado como, por exemplo: echo "$foo" | sed 's/a/b/i ou fornecer uma classe de caractere: echo ${foo//[aA]/b}.

Resposta

Você pode usar a ferramenta POSIX ex:

ex a.txt <<eof %s/Sunday/Monday/g xit eof 

https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ex.html

Comentários

  • muito obrigado. apenas para adicionar, o sinalizador -c é para executar o comando quando a edição começar (já que ex é um editor) e o sinalizador -s é o modo de script desabilitando o feedback ou como alguns dizem o modo slient. ref para mais informações: ex-vi.sourceforge.net/ex.html

Resposta

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

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

Deve estar disponível em qualquer * nix. A vírgula em ",s/a/b/g" informa ed para trabalhar em cada linha (você também pode usar %, que será mais familiar se você “estiver acostumado com o vim), e o resto disso é uma busca e substituição padrão. w diz para escrever (salvar) o arquivo, q diz para ele sair.

Observe que, ao contrário opção sed “s -i (e opções semelhantes em outras ferramentas), isso realmente edita o arquivo no local em vez de trapacear com arquivos temporários.

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

Resposta

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

Apenas imprimindo em STDOUT :

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

substituindo no local:

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

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *