Encontre e substitua o texto em um arquivo usando comandos

Respostas:

1053
sed -i 's/original/new/g' file.txt

Explicação:

  • sed = Stream EDitor
  • -i = no local (ou seja, salve de volta no arquivo original)
  • A cadeia de comando:

    • s = o comando substituto
    • original = uma expressão regular que descreve a palavra a substituir (ou apenas a própria palavra)
    • new = o texto para substituí-lo por
    • g = global (isto é, substitua tudo e não apenas a primeira ocorrência)
  • file.txt = o nome do arquivo

cscarney
fonte
3
@ Akiva Se você incluir caracteres especiais regex na sua pesquisa sed, eles corresponderão a eles. Adicione uma -rbandeira se desejar usar REs estendidos.
Cscarney # 28/14
32
@mcExchange Se for especificamente o /caractere que você precisa corresponder, você pode usar outro caractere como separador (por exemplo 's_old/text_new/text_g'). Caso contrário, você pode colocar um \ antes de qualquer um $ * . [ \ ^para obter o caractere literal.
Cscarney 12/08/2015
3
@BrianZ No que diz respeito ao sistema de arquivos, a saída do sed é um novo arquivo com o mesmo nome. É um dos erros relatados que não são erros
cscarney
17
O comando OSX sed -i '.bak' 's/original/new/g' file.txttambém pode ser executado com uma extensão de comprimento zero sed -i '' 's/original/new/g' file.txt, que não gerará backup.
Kirk
20
Os usuários do MacOS precisarão adicionar '' "após -i como parâmetro para -i ed.gs/2016/01/26/os-x-sed-invalid-command-code para que o arquivo seja substituído.
geoyws
32

Existem várias maneiras diferentes de fazer isso. Um está usando sede Regex. O SED é um editor de fluxo para filtrar e transformar texto. Um exemplo é o seguinte:

marco@imacs-suck: ~$ echo "The slow brown unicorn jumped over the hyper sleeping dog" > orly
marco@imacs-suck: ~$ sed s/slow/quick/ < orly > yarly
marco@imacs-suck: ~$ cat yarly
The quick brown unicorn jumped over the hyper sleeping dog

Outra maneira que pode fazer mais sentido do que < strine > strouté com canos!

marco@imacs-suck: ~$ cat yarly | sed s/unicorn/fox/ | sed s/hyper/lazy/ > nowai
marco@imacs-suck: ~$ cat nowai 
The quick brown fox jumped over the lazy sleeping dog
Marco Ceppi
fonte
6
observe o catno cat file | sed '...'é desnecessário. Você pode dizer diretamente sed '...' file.
Fedorqui 9/10/2015
1
Na verdade, isso pode ser reduzido ainda mais: sed -i'.bak' -e 's/unicorn/fox/g;s/hyper/brown/g' yarlylevará o arquivo rapidamente e fará as duas alterações no local enquanto faz um backup. Usando o time bash -c "$COMMAND"tempo, sugere que esta versão é ~ 5 vezes mais rápida.
pbhj
23

Existem várias maneiras de conseguir isso. Dependendo da complexidade do que se tenta obter com a substituição de cadeias, e dependendo das ferramentas com as quais o usuário está familiarizado, alguns métodos podem ser preferidos mais que outros.

Nesta resposta, estou usando um input.txtarquivo simples , que você pode usar para testar todos os exemplos fornecidos aqui. O conteúdo do arquivo:

roses are red , violets are blue
This is an input.txt and this doesn't rhyme

BATER

O Bash não é realmente destinado ao processamento de texto, mas substituições simples podem ser feitas via expansão de parâmetros , em particular aqui podemos usar estrutura simples ${parameter/old_string/new_string}.

#!/bin/bash
while IFS= read -r line
do
    case "$line" in
       *blue*) printf "%s\n" "${line/blue/azure}" ;;
       *) printf "%s\n" "$line" ;;
    esac
done < input.txt

Esse pequeno script não substitui no local, o que significa que você precisaria salvar o novo texto em um novo arquivo e se livrar do arquivo antigo, ou mv new.txt old.txt

Nota lateral: se você está curioso para saber por que while IFS= read -r ; do ... done < input.txté usado, é basicamente a maneira do shell de ler o arquivo linha por linha. Veja isto para referência.

AWK

O AWK, sendo um utilitário de processamento de texto, é bastante apropriado para essa tarefa. Pode fazer substituições simples e muito mais avançadas com base em expressões regulares . Ele fornece duas funções: sub()e gsub(). O primeiro substitui apenas a primeira ocorrência, enquanto o segundo substitui ocorrências em toda a cadeia. Por exemplo, se tivermos string one potato two potato, este seria o resultado:

$ echo "one potato two potato" | awk '{gsub(/potato/,"banana")}1'
one banana two banana

$ echo "one potato two potato" | awk '{sub(/potato/,"banana")}1'                                      
one banana two potato 

O AWK pode usar um arquivo de entrada como argumento; assim, fazer as mesmas coisas input.txtseria fácil:

awk '{sub(/blue/,"azure")}1' input.txt

Dependendo da versão do AWK que você possui, ela pode ou não ter edição no local; portanto, a prática usual é salvar e substituir o novo texto. Por exemplo, algo como isto:

awk '{sub(/blue/,"azure")}1' input.txt > temp.txt && mv temp.txt input.txt

SED

Sed é um editor de linha. Ele também usa expressões regulares, mas para substituições simples é suficiente:

sed 's/blue/azure/' input.txt

O que há de bom nessa ferramenta é que ela possui edição no local, que você pode ativar com o -isinalizador.

Perl

O Perl é outra ferramenta frequentemente usada para processamento de texto, mas é uma linguagem de uso geral e é usada em redes, administração de sistemas, aplicativos de desktop e muitos outros locais. Ele emprestou muitos conceitos / recursos de outras linguagens como C, sed, awk e outros. A substituição simples pode ser feita da seguinte maneira:

perl -pe 's/blue/azure/' input.txt

Como sed, o perl também tem a bandeira -i.

Pitão

Esse idioma é muito versátil e também é usado em uma ampla variedade de aplicações. Ele tem muitas funções para trabalhar com strings, entre as quais replace(), portanto, se você tiver variáveis ​​como var="Hello World", poderá fazervar.replace("Hello","Good Morning")

A maneira simples de ler o arquivo e substituir a string seria assim:

python -c "import sys;lines=sys.stdin.read();print lines.replace('blue','azure')" < input.txt

No entanto, com o Python, você também precisa gerar um novo arquivo, o que também pode ser feito no próprio script. Por exemplo, aqui está um exemplo simples:

#!/usr/bin/env python
import sys
import os
import tempfile

tmp=tempfile.mkstemp()

with open(sys.argv[1]) as fd1, open(tmp[1],'w') as fd2:
    for line in fd1:
        line = line.replace('blue','azure')
        fd2.write(line)

os.rename(tmp[1],sys.argv[1])

Este script deve ser chamado input.txtcomo argumento da linha de comando. O comando exato para executar o script python com argumento da linha de comando seria

 $ ./myscript.py input.txt

ou

$ python ./myscript.py input.txt

Obviamente, verifique se ele ./myscript.pyestá no seu diretório de trabalho atual e, pela primeira vez, verifique se ele está definido como executável comchmod +x ./myscript.py

O Python também pode ter expressões regulares, em particular, existe um remódulo, que tem re.sub()função, que pode ser usado para substituições mais avançadas.

Sergiy Kolodyazhnyy
fonte
1
Boa compilação! Outra maneira possível não mencionada aqui é usar o trcomando no unix
Tapajit Dey
1
@TapajitDey Sim, tr é outra ótima ferramenta, mas observe que é para substituir conjuntos de caracteres (por exemplo tr abc cde, traduzir apara c, bpara d. É um pouco diferente de substituir palavras inteiras como com sedoupython
Sergiy Kolodyazhnyy
22

Você pode usar o Vim no modo Ex:

ex -s -c '%s/OLD/NEW/g|x' file
  1. % selecione todas as linhas

  2. s substituto

  3. g substitua todas as instâncias em cada linha

  4. x escreva se as alterações foram feitas (elas têm) e saia

Steven Penny
fonte
21

Através do comando gsub do awk,

awk '{gsub(/pattern/,"replacement")}' file

Exemplo:

awk '{gsub(/1/,"0");}' file

No exemplo acima, todos os 1s são substituídos por 0, independentemente da coluna em que ela se localizou.


Se você deseja fazer uma substituição em uma coluna específica, faça o seguinte,

awk '{gsub(/pattern/,"replacement",column_number)}' file

Exemplo:

awk '{gsub(/1/,"0",$1);}' file

Ele substitui 1 por 0 apenas na primeira coluna.

Através do Perl,

$ echo 'foo' | perl -pe 's/foo/bar/g'
bar
Avinash Raj
fonte
Eu usei isso no terminal MacOS e ele não fez nada ...
Jim
Testado em Alpine Linux (no recipiente Docker) e ficou sem saída
Salatiel Genèse
@ SalathielGenèse, o que você está tentando alcançar?
Avinash Raj
Eu estou vendo arquivo com inotifywaitsob shenv, e comunicação de dados em formato CSV (porque formato personalizado é buggy). Eu então imaginei que não havia uma maneira simples de lidar com documentos CSV em scripts de shell ... E eu quero muito leve. Então, iniciei um script bastante simples para analisar e relatar CSV. Li a especificação CSV e notei que ela é mais elaborada do que eu esperava e apóio o valor de várias linhas envolto em aspas duplas. Eu estava contando com seda tokenização, mas logo percebi que mesmo o que sedchamam multilinhas é de até duas linhas. E se um dos meus valores de CSV se estender por mais de duas linhas?
Salathiel Genèse
melhor perguntar o seu problema como pergunta.
Avinash Raj
8

sedé o s tream ed itor , em que você pode usar |(pipe) para enviar fluxos padrão (STDIN e STDOUT especificamente) através de sede alterá-los por meio de programação em tempo real, tornando-se uma ferramenta útil na filosofia tradição Unix; mas também pode editar arquivos diretamente, usando o -iparâmetro mencionado abaixo.
Considere o seguinte :

sed -i -e 's/few/asd/g' hello.txt

s/é utilizado para s ubstitute a expressão encontrado fewcom asd:

Os poucos, os corajosos.


O asd, o corajoso.

/gsignifica "global", o que significa fazer isso para toda a linha. Se você deixar de /g(com s/few/asd/, sempre precisará haver três barras, não importa o que) e fewaparecer duas vezes na mesma linha, somente a primeira fewserá alterada para asd:

Os poucos homens, as poucas mulheres, os corajosos.


Os homens asd, as poucas mulheres, os corajosos.

Isso é útil em algumas circunstâncias, como alterar caracteres especiais no início das linhas (por exemplo, substituir os símbolos maiores que algumas pessoas usam para citar o material anterior nos threads de email por uma guia horizontal, deixando uma desigualdade algébrica entre aspas mais adiante. intocado), mas no seu exemplo em que você especifica que em qualquer lugar few ocorre, ele deve ser substituído, verifique se possui /g.

As duas opções a seguir (sinalizadores) são combinadas em uma -ie:

-iopção é usada para editar i n colocar no arquivo hello.txt.

-eopção indica o e xpression / comando para executar, neste caso s/.

Nota: É importante que você use -i -epara pesquisar / substituir. Nesse caso -ie, você cria um backup de cada arquivo com a letra 'e' anexada.

Chaminda Bandara
fonte
2

Você pode fazer assim:

locate <part of filaname to locate> | xargs sed -i -e "s/<Old text>/<new text>/g" 

Exemplos: para substituir todas as ocorrências [logdir ',' '] (sem []) por [logdir', os.getcwd ()] em todos os arquivos resultantes do comando Locate, faça:

ex1:

locate tensorboard/program.py | xargs sed -i -e "s/old_text/NewText/g"

ex2:

locate tensorboard/program.py | xargs sed -i -e "s/logdir', ''/logdir', os.getcwd()/g"

onde [tensorboard / program.py] é um arquivo para pesquisar

Nguyễn Tuấn Anh
fonte
Oi. Sua escolha de strings ( logdir', ''-> /logdir', os.getcwd()) dificulta a análise desta resposta. Além disso, vale a pena especificar que sua resposta primeiro localiza os arquivos a serem usados ​​no sed, porque isso não faz parte da pergunta.
Mwfearnley 22/08
Olá, esta resposta é pesquisar e substituir tudo se encontrou <texto antigo> no arquivo.
Nguyễn Tuấn Anh
Eu escolho esta resposta para todos que usam o tensorboard no keras, que desejam alterar o comando de: tensorboard --logdir = '/ caminho / para / log / pasta /' para usar: apenas tensorboard, quando permanecer na pasta de logs. é muito conveniente
Nguyễn Tuấn Anh