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
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 ed (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 !
$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.