linhas de comando e scripts com uso do sed na edição de arquivos textos ou dados passados pelo pipe |.
sed é uma linguagem com muitas funcionalidades, excelente na manipulação de strings e arquivo texto, muito útil na linha de comando e scripts, também em combinação com outros aplicativos como cat, ls e etc...
+sed ~linux, exemplos: apagar linha +sed ~linux trocar palavra +sed ~linux Re: sed ~linux sed ~linux how to sed ~linuxUse e abuse da criatividade, tente com outras variações.
Caso não encontre em sua intalação, use o gerenciador de pacotes e procure "sed"
Depois de instalado consulte a página do manual
man sed
Ver a versão do sed
sed -V
sed --version
trocar, substituir palavra ou frase dentro de um arquivo.
Normalmente se usa como delimitador a "/" barra normal e a barra invertida "\" pra indicar que o proximo caracter é um simbolo.
Também pode usar como delimitador a "|".
sed = Stream Editor.
sed é uma ferramenta poderosa pra manipular arquivos, muito útil e pratica pra utilizar em scripts ou linha de comando sem precisar de usar um editor de texto abrir o arquivo, alterar e salvar.
Com o sed altera arquivos como se faz com o editor de texto, com a diferença que faz isto em linha de comando sem o trabalho de abrir o arquivo no editor de texto, exemplo de linha de comando para troca de palavra em todo o documento.
sed "s/stringoriginal/stringtroca/g" arquivooriginal > arquivotroca | | | | | | | | | | | |_arquivo modificado | | | | |_ arquivo original permanece inalterado | | | |_ aplicar em todas ocorrencias do arquivo | | |__ nova palavra ou frase que substituirá stringoriginal | |___palavra o frase a ser substituida |____ s = substituir
Caracteres especiais requer uma \ antes do simbolo para não ser interpretado pelo shell, exemplo na troca de todos os .(ponto) por _(underline).
sed "s/\./_/g" arquivooriginal > arquivotroca
Exemplo com barra normal "/" na frase que quer trocar, neste exemplo a linha original no squid.conf;
#acl our_networks src 192.168.1.0/24 192.168.2.0/24
Remover o comentário para ficar assim;
acl our_networks src 192.168.1.0/24 192.168.2.0/24
Colar a linha abaixo no console para fazer a troca, observer que é uma única linha e tem a "\" antes de cada ponto e também antes de cada barra normal indicando que o caracter seguinte deve ser mantido, escapando com \ para não serem interpretados nem não confundir o caracter seguinte com parametros do sed.
sed -i "s/#acl our_networks src 192\.168\.1\.0\/24 192\.168\.2\.0\/24/acl our_networks src 192\.168\.1\.0\/24 192\.168\.2\.0\/24/g" /etc/squid/squid.conf
Trocar o delimitador, usando como delimitador "|', não precisa da "\" (escapar) antes da "/" veja o resultado para alterar zago por backup/docs no arquivo contendo estas linhas.
/home/zago/guiaz/ /home/zago/evolution/ /home/zago/doc/
sed -e "s|/zago|/backup/docs|" /tmp/teste/backup.sh
Não precisou da \ antes de cada / porque usou outro delimitador, retorna.
/home/backup/docs/guiaz/ /home/backup/docs/evolution/ /home/backup/docs/doc/
Com -e pode incluir expressções como final de linha $, inicio de linha ^ e etc..
Redirecinar a saida para outro arquivo como nos exemplos acima ou com a diretiva -i (in place) para alterar no proprio arquivo.
sed -i "s/stringoriginal/stringtroca/g" arquivo
Evite acidentes, procure redirecionar a saida para outro arquivo ou faça copia antes de aplicar as alterações.
Exemplo com o texto de arquivo.txt
cat arquivo.txt
Neste arquivo tem zago, com o comando sed todas as ocorrencias da palavra zago serão modificadas pra Antonio Francisco Zago, compare os dois arquivos.
sed "s/zago/Antonio Francisco Zago/g" arquivo.txt > arquivomodificado.txt
cat arquivomodificado.txt
Neste arquivo tem Antonio Francisco Zago, com o comando sed todas as ocorrencias da palavra Antonio Francisco Zago serão modificadas pra Antonio Francisco Zago, compare os dois arquivos.
No exemplo acima o sed modificou o conteúdo do arquivo, onde encontrou a palavra "zago" fez a substituição por "Antonio Francisco Zago" sem precisar usar um editor de texto para abrir o arquivo fazer a troca e salvar, em uma única linha de comando o sed executou esta tarefa em todo o arquivo.
Remover palavras ou strings de um documento.
sed "s/zago//g" arquivo.txt > arquivomodificado.txt
cat arquivomodificado.txt
Neste arquivo tem o nome , com o comando sed todas as ocorrencias da palavra serão modificadas para Antonio Francisco Zago, compare os dois arquivos.
No exemplo acima não indica nova string, está vazia e portanto a palavra "zago" foi removida, substituida por um campo vazio, veja que também é case sensitive, não modificou Zago com Z maiusculo.
Aplicar determinado comando em todos arquivos de um diretório.
Nestes casos o melhor é montar um script, quando todos tem a mesma terminação ou nomes que permite selecionar com curinga no nome, exemplo para aplicar em todos arquivos .txt
sed -i 's/stringoriginal/stringtroca/g' *.txt
sed -i "s/stringoriginal/stringtroca/g" *.txt
Apagar, remover a string encontrada.
sed -i "s/stringoriginal//g" *.txt
Pegar somente palavras separadas por espaços, use a barra para escapar, indicar um espaço, neste exemplo abaixo tem a \ mais espaço antes e depois de string, ou \s (barra mais espaço ou barra mais a letra s). Neste caso procura pela string entre espaços.
sed 's/\ string\ //g'
sed 's/\ stringvelha\ /\ stringnova\ /g'
sed 's/\sstring\s//g'
Veja alguns resultados, para trocar basta incluir a novastrint entre as duas barras "//"no final do comando, no exemplo abaixo remove porque não informou a string de troca.
echo "Antonio Francisco Zago" | sed 's/\ cisco\ //g' Antonio Francisco Zago echo "Antonio Francisco Zago" | sed 's/cisco//g' Antonio Fran Zago echo "Antonio Francisco Zago" | sed 's/\ Francisco\ //g' AntonioZago echo "Antonio Francisco Zago" | sed 's/\sFrancisco\s//g' AntonioZago echo "Antonio Francisco Zago" | sed 's/\ Francisco\ /\ troca\ /g' Antonio troca Zago
Combinar palavra com inicio ou final de linha
^ indica inicia de linha ^palavra trata somente palavra no inicio da linha, ignora a mesma palavra nas demais partes da linha.
$ indica final de linha palavra$ trata somente palavra no final da linha, ignora a mesma palavra nas demais partes da linha.
sed 's/^/texto adicionado/' sed -i 's/^/texto adicionado/' meuarq.txt Incluir um TAB para manter o formato na conversão em HTML pelo txt2tags sed -i 's/^/\t/' meuarq.txt Ou para manter como item, acrescentar dois pontos mais um espaço no inicio de cada linha. sed -i 's/^/ /' meuarq.txt
Inserir comentário (#) somente nas linhas que inciam com /home/zago
sed -r 's|(^/home/zago)|#\1|g' arquivo.txt
/home/backup /home/backup/home/zago #/home/zago/guiaz/ #/home/zago/doc/ /etc/
onde \1 mantém a string de procura, sem \1 faz a troca ou precisa repetir a string de procura, comandos sem \1 e equivalentes.
sed -r 's|(^/home/zago)|#/home/zago|g' arquivo.txt
sed -r 's|^/home/zago|#/home/zago|g' arquivo.txt
Linha de comando para alterar o conteúdo da terceira linha para 1, aplico esta linha para alterar de 5 para 1 o numero do CD na criação do DVD do SUSE.
sed -i "3s/^./1/" /tmp/sl101dvd/media.1/media | || | | | |_arquivo que vai aplicar a modificação | || | | |_caminho do arquivo a ser modificado | || | |_ alteração a ser efetuada, novo caracter ou conteúdo da linha | || |_inicio da linha | ||__ s = substituir | |___3 indica a linha para aplicar alteração, somente esta será afetada |____aplicar alteração no próprio arquivo
Alterar somente em linhas com determinada palavra, trocar a palavra velha por nova somente nas linhas que contém a palavra estado.
sed -i '/estado/s/velha/nova/g' arquivo.txt
Observe o uso do sed no script abaixo, a linha;
arqespac=`echo $i | sed 's:\.: :g'`
echo passa o nome do arquivo em $1, sed troca todos os ponto no nome do arquivo por espaço, na linha seguinte awk pega a primeira coluna, awd usa o espaço como separador de colunas, ou seja, pega a parte do nome que vem antes do primeiro ponto ignorando o resto do nome, basename também faz esta tarefa, mas não atende ao meu caso porque tenho variação muito grande no nome dos arquivos e preciso somente da parte do nome que vem antes do primeiro ponto, aplico este script para converter páginas do man em HTML
#!/bin/bash for i in *.gz ; do #coloque aqui seus comandos arqespac=`echo $i | sed 's:\.: :g'` nome=`echo $arqespac | awk '{print $1}'` man ./$i | man2html -title man\ $nome -topm 5 > $nome.html done
Limpando as linhas em branco com sed, linhas em branco sem espaços, (^$) pega somente as linhas com sinal de fim de linha ($) no inicio da linha (^), ou seja, linha em branco, inicia com final de linha.
sed '/^$/d' squid.conf > squid.conf-sed
sed '/^$/d;' squid.conf > squid.conf-sed
Com espaços na linha em branco
cat arq.txt | sed '/^ *$/d' > arqlimpo.txt
Remover linhas que inicial com tab, utilizo nos resultados do comando diff em duas colunas.
cat /tmp/arqtmp.txt | sed '/^\t/d' > /tmp/arqlimpo.txt
Eliminar a primeira linha do arquivo:
sed 1d teste > testesemlinha1
ou sed -i 1d teste
Eliminar a ultima linha de uma arquivo:
sed '$d' teste
Eliminar as ultimas 9 linhas de uma arquivo:
sed -i -e :a -e '$d;N;2,9ba' -e 'P;D' teste.txt
Esta linha é copia do site do Thbias, no original é pra 10 linhas, aqui modificado pra 9 linhas e acrescentado a diretiva -i para modificar o proprio arquivo.
Com o comando acima não exibe no video a ultima linha, para salvar a alterarção, grave o resultado em outro arquivo ex:
sed '$d' teste > testesemultimalinha
Ou para modificar o proprio arquivo use -i, exemplo:
sed -i '$d' teste
Remover uma faixa de linhas, por exemplo da 2 até a 10 e salvar em outro arquivo:
sed -e '2,10d' teste > testenovo
Remover no proprio arquivo da linha 1 até a 22
sed -i '1,22d' teste
Apagar todas as linhas com determinada string:
sed -i '/As partes desta mensagem/Id' texto.txt sed -i '/sexta/Id' texto.txt
Remover linha que inicia com IP 192.168.1.205, utilizo para remover chave de IP que foi moficado no arquivo ~/.ssh/known_hosts
sed -i '/^192.168.1.205/d' ~/.ssh/known_hosts
Faça testes com copia do arquivo em /tmp
sed -i '/^192.168.1.205/d' /tmp/known_hosts
Em minhas instalações de testes isto é repetitivo, para não ficar repetindo a digitação, coloquei no inicio do .bash_history, outra opção que utilizo, criar script e passar o IP na linha de comando, script que utilizo em minhas instalações.
cat /usr/bin/zzsedip
#!/bin/bash sed -i "/^$1/d" ~/.ssh/known_hosts
Com este script basta passar o IP na linha de comando, digitar zzse e tecla tab para completar, depois tecle um espaço e IP que deseja remover
zzsedip 192.168.1.205
Agora é só voltar com as setas até a linha que deu erro e dar enter para criar nova chave e completar a conexão...
Executar uma sequencia de comandos nos arquivos listados em arqlista, não use ponto ou caracteres especiais no nome deste arquivo, execute o script dentro do diretório onde estão os arquivos a serem modificados, este script é uma versão simplificada para limpar arquivos com download de messagens da lista de shell-script no yahoo, são arquivos pequenos e não tive preocupação com velocidade e outros detalhes, somente remover cabeçalhos e rodapé dos textos, funciona!.
#!/bin/bash for i in $( cat arqlista );do # exibir o nome do arquivo sendo processado echo $i # apagar da linha 1 até a 22 sed -i '1,22d' "$i" # depois apaga a linha 2 e 3 sed -i '2,3d' "$i" # apagar todas as linhas que contem "As partes desta mensagem" sed -i '/As partes desta mensagem/Id' "$i" # apagar as ultimas 9 linhas sed -i -e :a -e '$d;N;2,9ba' -e 'P;D' "$i" done
Exibir o nome do arquivo sendo processado, acrescente esta linha
echo $i
Pegar somente o nome de arquivos sem a extensão, exemplo de como procurar com find pelos arquivos .txt e retornar o nome sem a extensão.
find /tmp/guiaz -name "*.txt" -exec basename {} \; | sed s/"\.txt"//g
basename também faz esta função, man basename
Varios exemplos com a mesma finalidade, alterar string em arquivos.
Dicas-l alterou o dominio, trocou unicamp por com, tenho muitas indicações e algumas copias de mensagens com o endereço antigo, no inicio solicitei ao Rubens para corrigir o endereço e fui prontamente atendido, depois constatei que ocorria em todos endereços, a linha de comando abaixo alterou todos arquivos no FAQ.
Mostrando o resultado antes de alterar. grep "Dicas-L.unicamp.br/" -r /home/zago/guiaz/ Contando as ocorrencias grep "Dicas-L.unicamp.br/" -r /home/zago/guiaz/ | wc -l 538 Localizar e substituir em todos arquivos find /home/zago/guiaz -name "*.*" -exec sed -i s/"Dicas-L.unicamp.br"/Dicas-l.com.br/g {} \;
Detalhe, alterou estatus de todos arquivos para modificados, até mesmo os que não teve alteração, como tenho um script que atualiza o site com os arquivos modificados nas ultimas 24 horas, isto forçou upload de todos arquivos para o site, quado for o caso, considere criar script para detectar com grep quais arquivos deve aplicar o sed.
Depois da alteração ainda restou endereços com "dicas-l.unicamp.br", resolvi fazer de outra forma, com sed acessando e alterando somente os arquivos com a expressão de procura.
#!/bin/bash grep "dicas-l.unicamp.br/" -r /home/zago/guiaz/ | cut -d":" -f1 | sort -u > /tmp/altera.txt for i in `cat /tmp/altera.txt` do # testar para ver se está mostrando os arquivos corretos, # quando OK remova o comentário da linha do sed para alterar echo $i # sed -i s/"dicas-l.unicamp.br"/dicas-l.com.br/g $i done
Conferir se o numero de arquivos alterados coincide com a listagem do arquivo, compare a contagem.
find /home/zago/guiaz -type f -mmin -3 | wc -l 80 cat /tmp/altera.txt | wc -l 80
Trocar @ por # em e-mail nas mensagens do FAQ
Recebi esta dica de Tulio Miranda Barros <tmbarros # myrealbox.com>
for i in * ; do mv $i 0 ; sed 's/@/#/g' 0 > $i ; rm 0 ; done
Achei melhor não executar esta linha porque altera todos os arquivos, inclusive o @ usando em outros locais como arquivos de configuração, coloquei um aviso na página inicial (menu.html) para alterar somente de quem solicitar.
Por enquanto precisa editar o script para alterar e-mail ( em 3 posições), na troca pode informa ( at ), ou simbolos como ( # ), com espaço ou sem. Para uso eventual está bom, mas tem como melhorar e passar os dados por parametro.
Exemplo para trocar (@) por ( # ) de todos e-mail de zagolinux@gmail.com
#!/bin/bash grep -r zagolinux@uol.com.br /tmp/guiaz/ | cut -d":" -f1 | sort -u > /tmp/altera.txt for i in `cat /tmp/altera.txt` do # faça testes e backup antes de qualquer alteração. sed -i s/zagolinux@uol.com.br/zagolinux\ \#\ uol.com.br/g $i done
antes e depois
zagolinux # gmail.com
Uma maneira prática, usar seu editor de texto para alterar a linha de comando, copiar e colar no console, quando vai executar uma única vez, torna mais rápido e prático que criar script, pode quebrar a linha com barra invertida \ ou juntar tudo e usar ; para indicar nova linha, este exemplo pode copiar e colar todas as linhas no console.
for i in `cat /tmp/altera.txt` do echo $i sed -i s/"dicas-l.unicamp.br"/dicas-l.com.br/g $i done depois de colar mostra estas linhas no console, basta um enter para executar. for i in `cat /tmp/altera.txt` > do > echo $i > sed -i s/"dicas-l.unicamp.br"/dicas-l.com.br/g $i > done
Ou use ; para indicar próxima linha, assim agrupa todos os comandos em um únia linha como esta.
for i in `cat /tmp/altera.txt`; do echo $i; sed -i s/"dicas-l.unicamp.br"/dicas-l.com.br/g $i; done
Outros exemplos para aplicar o sed e fazer a mesma alteração em arquivos do diretório corrente, observe o primeiro exemplo a seguir (*.txt) pegando somente esta terminação e o segundo pegando tudo (ls). Não desce nos sub-diretórios, afeta somente arquivos dentro do diretório corrente, no exemplo anterior com find procura e altera também nos sub-diretórios.
for i in *.txt; do cat $i | sed 's/dicas-l.unicamp.br/dicas-l.com.br/g' > /tmp/teste/$i.tmp; done
for i in `ls`; do cat $i | sed 's/dicas-l.unicamp.br/dicas-l.com.br/g' > /tmp/teste/$i.tmp; done
Procura por (Dicas-L.unicamp.) e troca o (unicamp) por (com) altera somente quando unicamp for precedido da empressão entre parenteses (Dicas-L.), o ponto foi usado para não pegar outras expressões, a barra antes do ponto é para tratar como caractere do texto, escapar da interpretação dele como ponto na expressão.
for i in *.txt; do sed -ri 's/(Dicas-L\.)unicamp\./\1com\./g' $i; done
alterar com tr
tr . _ < arquivo