bash - trabalhando - utilizando o sed no linux




Localizar e substituir dentro de um arquivo de texto de um comando Bash (10)

Qual é a maneira mais simples de encontrar e substituir uma determinada string de entrada, digamos abc , e substituir por outra string, digamos XYZ no arquivo /tmp/file.txt ?

Estou escrevendo um aplicativo e usando o IronPython para executar comandos por meio do SSH - mas não conheço bem o Unix e não sei o que procurar.

Ouvi dizer que o Bash, além de ser uma interface de linha de comando, pode ser uma linguagem de script muito poderosa. Então, se isso for verdade, suponho que você pode executar ações como essas.

Posso fazê-lo com o bash e qual é o script mais simples (uma linha) para atingir meu objetivo?


A maneira mais fácil é usar sed (ou perl):

sed -i -e 's/abc/XYZ/g' /tmp/file.txt

Que irá chamar sed para fazer uma edição no local devido à opção -i . Isso pode ser chamado de bash.

Se você realmente quer usar apenas bash, então o seguinte pode funcionar:

while read a ; do echo ${a//abc/XYZ} ; done < /tmp/file.txt > /tmp/file.txt.t ; mv /tmp/file.txt{.t,}

Isso faz um loop sobre cada linha, fazendo uma substituição e gravando em um arquivo temporário (não quer estrobrar a entrada). O movimento no final apenas se move temporariamente para o nome original.


A manipulação de arquivos normalmente não é feita pelo Bash, mas pelos programas invocados pelo Bash, por exemplo:

> perl -pi -e 's/abc/XYZ/g' /tmp/file.txt

O sinalizador -i diz para fazer uma substituição no local.

Veja man perlrun para mais detalhes, incluindo como fazer um backup do arquivo original.


Encontrei este tópico entre outros e eu concordo que contém as respostas mais completas, então eu adiciono o meu também:

1) sed e ed são tão úteis ... à mão !!! Veja este código do @Johnny:

sed -i -e 's/abc/XYZ/g' /tmp/file.txt

2) quando a minha restrição é usá-lo por um script de shell, nenhuma variável pode ser usada no lugar de abc ou XYZ! This parece concordar com o que eu entendo pelo menos. Então, não posso usar:

x='abc'
y='XYZ'
sed -i -e 's/$x/$y/g' /tmp/file.txt
#or,
sed -i -e "s/$x/$y/g" /tmp/file.txt

Mas o que nós podemos fazer? Como, @Johnny disse usar um 'while read ...' mas, infelizmente, esse não é o fim da história. O seguinte funcionou bem comigo:

#edit user's virtual domain
result=
#if nullglob is set then, unset it temporarily
is_nullglob=$( shopt -s | egrep -i '*nullglob' )
if [[ is_nullglob ]]; then
   shopt -u nullglob
fi
while IFS= read -r line; do
   line="${line//'<servername>'/$server}"
   line="${line//'<serveralias>'/$alias}"
   line="${line//'<user>'/$user}"
   line="${line//'<group>'/$group}"
   result="$result""$line"'\n'
done < $tmp
echo -e $result > $tmp
#if nullglob was set then, re-enable it
if [[ is_nullglob ]]; then
   shopt -s nullglob
fi
#move user's virtual domain to Apache 2 domain directory
......

3) Como se pode ver se nullglob está configurado então, ele se comporta estranhamente quando há uma string contendo um * como em

<VirtualHost *:80>
 ServerName www.example.com

que se torna

<VirtualHost ServerName www.example.com

não há um colchete angular final e o Apache2 não pode carregar!

4) Esse tipo de análise deve ser mais lento que a pesquisa e substituição de um clique, mas, como você já viu, existem 4 variáveis ​​para 4 padrões de pesquisa diferentes trabalhando em um único ciclo de análise!

A solução mais adequada que posso pensar com as suposições dadas do problema.


Este é um post antigo, mas para qualquer pessoa que queira usar variáveis ​​como @centurian disse que aspas simples significam que nada será expandido.

Uma maneira simples de obter variáveis ​​é fazer a concatenação de strings, já que isso é feito pela justaposição no bash, o seguinte deve funcionar:

sed -i -e 's/'"$var1"'/'"$var2"'/g' /tmp/file.txt


Para editar o texto no arquivo de forma não interativa, você precisa de um editor de texto no local, como o vim.

Aqui está um exemplo simples de como usá-lo a partir da linha de comando:

vim -esnc '%s/foo/bar/g|:wq' file.txt

Isto é equivalente a @slim resposta do editor ex que é basicamente a mesma coisa.

Aqui estão alguns exemplos ex práticos.

Substituindo texto foo com bar no arquivo:

ex -s +%s/foo/bar/ge -cwq file.txt

Removendo espaços em branco à direita para vários arquivos:

ex +'bufdo!%s/\s\+$//e' -cxa *.txt

Veja também:


Se o arquivo em que você está trabalhando não é tão grande, e armazená-lo temporariamente em uma variável não é problema, então você pode usar a substituição de string Bash em todo o arquivo de uma só vez - não há necessidade de passar por isso linha por linha:

file_contents=$(</tmp/file.txt)
echo "${file_contents//abc/XYZ}" > /tmp/file.txt

Todo o conteúdo do arquivo será tratado como uma longa string, incluindo quebras de linha.

XYZ pode ser uma variável, por exemplo $replacement , e uma vantagem de não usar sed aqui é que você não precisa se preocupar que a string search ou replace possa conter o caractere delimitador de padrão sed (geralmente, mas não necessariamente, /). Uma desvantagem é não poder usar expressões regulares ou qualquer uma das operações mais sofisticadas do sed.


Você pode usar o comando rpl. Por exemplo, você quer mudar o nome do domínio em todo o projeto PHP.

rpl -ivRpd -x'.php' 'old.domain.name' 'new.domain.name' ./path_to_your_project_folder/  

Isso não é claro, mas é muito rápido e útil. :)


Você pode usar sed

sed -i 's/abc/XYZ/gi' /tmp/file.txt

Use -i para ignorar maiúsculas e minúsculas se não tiver certeza de que o texto encontrado seja abc ou ABC ou AbC , etc.

Você pode usar o find e o sed se não souber agora o seu nome de arquivo:

 find ./ -type f -exec sed -i 's/abc/XYZ/gi' {} \;

Encontre e substitua em todos os arquivos python:

find ./ -iname "*.py" -type f -exec sed -i 's/abc/XYZ/gi' {} \;

Você também pode usar python no script bash. Eu não tive muito sucesso com algumas das principais respostas aqui, e achei que isso funcionasse sem a necessidade de loops:

#!/bin/bash
python
filetosearch = '/home/ubuntu/ip_table.txt'
texttoreplace = 'tcp443'
texttoinsert = 'udp1194'

s = open(filetosearch).read()
s = s.replace(texttoreplace, texttoinsert)
f = open(filetosearch, 'w')
f.write(s)
f.close()
quit()

encontre ./ -tipo f -name "arquivo * .txt" | xargs sed -i-e / abc / xyz / g '







ironpython