Questão Localizar e substituir texto em um arquivo usando comandos


Como posso encontrar e substituir palavras específicas em um arquivo de texto usando a linha de comando?


437
2018-01-07 04:10


origem


Maio de seu interesse github.com/lucio-martinez/rch :-) - Lucio


Respostas:


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

Explicação:

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

    • s = o comando substituto
    • original = uma expressão regular descrevendo a palavra a ser substituída (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


728
2018-01-07 04:23



@mcExchange Se for especificamente o / caractere que você precisa corresponder, você pode usar apenas algum 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 caracter literal. - cscarney
@BrianZ No que diz respeito ao sistema de arquivos, a saída do sed é um novo arquivo com o mesmo nome. É um dos bugs comumente relatados que não são bugs - cscarney
Você pode querer s/\boriginal\b/new/g ao invés de s/original/new/g (\b corresponde a um limite de palavra) para substituir apenas palavras inteiras. - Chris Martin
O comando OSX sed -i '.bak' 's/original/new/g' file.txt també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
Usuários de MacOS terão que 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 sobrescrito. - geoyws


Existem várias maneiras diferentes de fazer isso. Um está usando sed e 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 < strin e > 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

26
2018-01-07 04:26



Note o cat dentro cat file | sed '...' é desnecessário. Você pode dizer diretamente sed '...' file. - fedorqui
De fato, isso pode ser ainda mais reduzido: sed -i'.bak' -e 's/unicorn/fox/g;s/hyper/brown/g' yarly vai pegar o arquivo e fazer as 2 alterações no local enquanto faz um backup. Usando time bash -c "$COMMAND" ao tempo sugere que esta versão é ~ 5 vezes mais rápida. - pbhj


Você pode usar o Vim no modo Ex:

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

  2. s substituto

  3. g substituir todas as ocorrências em cada linha

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


15
2018-04-16 18:36





Através do comando gsub do awk,

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

Exemplo:

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

No exemplo acima, todos os 1's são substituídos por 0, independentemente da coluna em que ele está localizado.


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

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

Exemplo:

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

Substitui 1 por 0 apenas na coluna 1.

Através do Perl,

$ echo 'foo' | perl -pe 's/foo/bar/g'
bar

14
2017-07-02 12:59



Eu usei isso no terminal MacOS e não fez nada ... - Jim


Há muitas maneiras de conseguir isso. Dependendo da complexidade do que se tenta alcançar com a substituição de strings 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 simples input.txt arquivo, 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

BASH

Bash não é realmente destinado ao processamento de texto, mas simples substituições podem ser feitas via expansão de parâmetro , 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

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

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

AWK

O AWK, sendo um utilitário de processamento de texto, é bastante apropriado para essa tarefa. Ele 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 as 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 

AWK pode ter um arquivo de entrada como argumento, fazendo as mesmas coisas com input.txt seria fácil:

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

Dependendo da versão do AWK que você tem, ele 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 linhas. Ele também usa expressões regulares, mas para substituições simples é suficiente fazer:

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

O que é bom nessa ferramenta é que ela tem uma edição no local, que você pode ativar com -i bandeira.

Perl

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

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

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

Python

Esta linguagem é muito versátil e também é usada em uma ampla variedade de aplicações. Tem muitas funções para trabalhar com strings, entre as quais replace(), então se você tem variável como var="Hello World" , você poderia fazer var.replace("Hello","Good Morning")

Maneira simples de ler arquivos e substituir strings seria assim:

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

Com o Python, no entanto, você também precisa gerar um novo arquivo, o que também pode ser feito a partir do próprio script. Por exemplo, aqui está uma 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 com input.txt como argumento de linha de comando.

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


12
2018-02-03 07:49





sed é o stream editor, em que você pode usar | (pipe) para enviar fluxos padrão (STDIN e STDOUT especificamente) através sed e alterá-los programaticamente rapidamente, tornando-se uma ferramenta útil na tradição da filosofia Unix; mas também pode editar arquivos diretamente, usando o -i parâmetro mencionado abaixo.
Considere o seguinte:

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

s/ é usado para sustituir a expressão encontrada few com asd:

Os poucos, os bravos.


O asd, o valente.

/g significa "global", significando fazer isso para toda a linha. Se você deixar o /g (com s/few/asd/, sempre precisa haver três barras, não importa o quê) e few aparece duas vezes na mesma linha, apenas o primeiro few é alterado para asd:

Os poucos homens, as poucas mulheres, os bravos.


Os homens do asd, as poucas mulheres, os bravos.

Isso é útil em algumas circunstâncias, como alterar caracteres especiais no início das linhas (por exemplo, substituir os símbolos de maior que algumas pessoas usam para citar o material anterior em encadeamentos de e-mail com uma guia horizontal, deixando uma inequação algébrica mais tarde na linha intocado), mas no seu exemplo onde você especifica que qualquer lugar  few ocorre deve ser substituído, verifique se você tem que /g.

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

-i opção é usada para editar Eun lugar no arquivo hello.txt.

-e opção indica o expression / comando para executar, neste caso s/.

Nota: é importante que você use -i -e pesquisar / substituir. Se você fizer -ie, você cria um backup de todos os arquivos com a letra 'e' anexada.


6
2017-11-23 09:00





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 []) com [logdir ', os.getcwd ()] em todos os arquivos que são resultado do comando locate, faça:

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

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


0
2017-07-24 02:13



Oi. Sua escolha de cordas (logdir', '' -> /logdir', os.getcwd()) faz esta resposta difícil de analisar. Além disso, vale a pena especificar que sua resposta primeiro localiza os arquivos para usar o sed, porque não faz parte da pergunta. - mwfearnley
Oi, esta resposta é tanto procurar e substituir tudo se encontrou <texto antigo> no arquivo. - Nguyễn Tuấn Anh
Eu escolhi esta resposta para todos eles usam tensorboard em keras, que querem mudar o comando de: tensorboard - logdir = '/ path / to / log / folder /' para usar: tensorboard apenas, quando ficar na pasta de logs. é muito conveniente - Nguyễn Tuấn Anh