Visite também: Br-Linux ·  VivaOLinux ·  LinuxSecurity ·  Dicas-L ·  NoticiasLinux ·  SoftwareLivre.org ·  [mais]
Voltar   Under-Linux.org Fóruns > UnderLinux Wiki
Wiki Classificados Galeria Reviews Jogos Comunidades RSS Feeds FAQ Termos de Uso Sobre
Cadastre-se FotosBlogs Lista de Membros Calendário Pesquisar Mensagens de Hoje Marcar Fóruns Como Lidos

Ferramentas pessoais
Publicidade

From UnderLinux Wiki

Tabela de conteúdo

Introdução

Este tutorial conterá dicas diversas de como usar o sed para problemas cotidianos e na confecção de scripts

O propósito deste manual é despertar sua curiosidade para esta poderosa ferramenta, aconselhamos seguir os links no final deste tutorial para aprofundar seus conhecimentos sobre o assunto.

Definição

O programa SED é um editor de Streams, mas o que são streams afinal?
Pense no tráfego de dados como água em um encanamento, agora pense que ao invés de gotas temos bits e que o cano é bem fino e que só deixa passar um bit de cada vez. Isso é uma Stream, bits enfileirados. Quando temos uma Stream em rede o nome muda, temos aí um Socket.
O SED é interativo?
Imagine o editor [Vim] ou o Emacs, eles são editores interativos, pelos quais vamos abrindo os arquivos a serem editados e então vamos interativamente, modificando o que queremos. O SED por sua vez pode apagar, por exemplo, a terceira linha de mil arquivos sem que tenhamos de abrir um a um, é por isso que dizemos que o SED é um editor não interativo.

Expressões Regulares

O SED pode usar Expressões regulares nos seus padrões de inserção ou substituição. Veja exemplos:

Para ler um arquivo de configuração qualquer, ocultando as linhas que iniciam com "#", ou seja, linhas comentadas
sed -e '/^#/d' /etc/services | less

O circunflexo, em expressões regulares, significa início de linha!

Exemplos de uso do SED

Veja o script abaixo, nele a cor branca bgcolor="#white" foi modificada para um cinza bgcolor="#eeeeee" e as modificações são aplicadas e então são criados os arquivos com as modificações no diretório pessoal ~/tmp.

#!/bin/bash
# Scrip para mudar background de arquivos html
# Criado: Sex 30/Dez/2005 hs 22:12
# ultima modificação: Sex 30 Dez 2005 22:15:06 BRST
for i in *.html
  do
  cat $i | sed 's/bgcolor="#white"/bgcolor="#eeeeee"/' > ~/tmp/$i
  done

Administradores de sistemas podem e devem usar o SED, pois isto poupa tempo. O scrip acima foi criado só para que a leitura de um manual (que tinha o background branco) ficasse menos cansativa.

cat arquivo.txt | sed '4q;d'

Substituições de texto (substituir as vírgulas [,] por hífens[-]):

cat arquivo.txt | sed 's/,/-/g'

Pegar somente o endereço de retorno

nslookup a.root-servers.net | tail -n 1 | sed s/Address:\ \ \ \ //

Colocar número de linhas de um arquivo em uma variável

var=`sed -n '$=' /etc/passwd`

Só para constar, outro modo de contar linhas de um arquivo seria

cat /caminho/para/o/arquivo | wc -l

Substituição

Um comando de substituição tem a seguinte sintaxe:

sed 's/texto_antigo/texto_novo/' arquivo.txt

Pode-se, retirando as aspas simples, que protegem o comando para não ser lido pelo bahs, colocar variáveis de modo que uma construção assim é possível:

sed s/texto_antigo/$var2/ arquivo.txt

as aspas simples são para que o conteúdo do comando seja interpretado pelo sed antes do Bash.
Obs: Não direcione a saída para o próprio arquivo, pois isto irá apaga-lo. Uma solução segura é fazer algo assim:

sed 's/texto_antigo/texto_novo/' arquivo.txt > arquivo2.txt
cat arquivo2.txt > arquivo.txt

insere 5 espaços em branco no ínicio de cada linha (faz o "offset" da pagina)

sed 's/^/     /'

substituir (achar e trocar) "foo" por "bar" em cada linha

sed 's/foo/bar/'             # troca somente a 1a instância de uma linha
sed 's/foo/bar/4'            # troca somente a 4a instância de uma linha
sed 's/foo/bar/g'            # troca TODAS as instâncias de uma linha

substitui "foo" por "bar" SOMENTE nas linhas que contem "baz"

sed '/baz/s/foo/bar/g'

Impressão

IMPRESSÃO SELETIVA DE CERTAS LINHAS:

# imprime as primeiras 10 linhas de um arquivo (emula o comportamento do "head")
sed 10q
# imprime a primeira linha de um arquivo (emula o "head -1")
sed q
# imprime as últimas 10 linhas de um arquivo (emula o "tail") 
sed -e :a -e '$q;N;11,$D;ba'
# imprime somente a última linha de um arquivo (emula o "tail -1")
sed '$!d'
# imprime somente as linhas que se encaixam na expressão regular 
# (emula o "grep")
sed -n '/regexp/p'           # método 1
sed '/regexp/!d'             # método 2
# imprime somente as linhas que NÃO se encaixam na regexp (emula o "grep -v")
sed -n '/regexp/!p'          # método 1, corresponde ao descrito acima
sed '/regexp/d'              # método 2, sintaxe mais simples
# imprime uma linha de contexto antes e depois da expressão regular,
# com o número da linha indicando onde a expressão regular 
# aparece (similar ao "grep -A1 -B1")
sed -n -e '/regexp/{=;x;1!p;g;$!N;p;D;}' -e h
# procura e imprime por AAA e BBB e CCC (em qualquer ordem)
sed '/AAA/!d; /BBB/!d; /CCC/!d'
# procura e imprime por AAA e BBB e CCC (nessa ordem)
sed '/AAA.*BBB.*CCC/!d'
# procura e imprime por AAA ou BBB ou CCC (emula o "egrep")
sed -e '/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d
# imprime um parágrafo se ele possuir AAA (linhas vazias separam os parágrafos).
# Com o HHsed v1.5 deve ser inserido o 'G;' apos o 'x;', nos 3 scripts abaixo
sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;'
# imprime um parágrafo se ele possuir AAA e BBB e CCC (em qualquer ordem)
sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;/BBB/!d;/CCC/!d'
# imprime o parágrafo inteiro se ele possuir AAA ou BBB ou CCC
sed -e '/./{H;$!d;}' -e 'x;/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d
# imprime somente as linhas com 65 caracteres ou mais
sed -n '/^.\{65\}/p'
# imprime somente as linhas com menos que 65 caracteres
sed -n '/^.\{65\}/!p'        # método 1, corresponde ao descrito acima
sed '/^.\{65\}/d'            # método 2, sintaxe mais simples
# imprime uma parte do arquivo que vai da expressão regular até
# o final do mesmo
sed -n '/regexp/,$p'
# imprime uma parte do arquivo baseada nos números das linhas (linhas 8-12,
# inclusive)
sed -n '8,12p'               # método 1
sed '8,12!d'                 # método 2
# imprime a linha de número 52
sed -n '52p'                 # método 1
sed '52!d'                   # método 2
sed '52q;d'                  # método 3, eficiente com arquivos grandes
# imprime um pedaço de arquivo que está entre as duas
# expressões regulares (inclusive)
sed -n '/Iowa/,/Montana/p'             # é case sensitive

Deleção

# imprime todo o arquivo EXCETO a parte entre 2 expressões regulares
sed '/Iowa/,/Montana/d'
# deleta linhas duplicadas de um arquivo (emula o "uniq"). A primeira
# linha de um conjunto de linhas duplicadas é mantida, o resto é deletada
sed '$!N; /^\(.*\)\n\1$/!P; D'
# deleta TODAS as linhas em branco de um arquivo (o mesmo que "grep '.' ")
sed '/^$/d'
# deleta todas as linhas brancas CONSECUTIVAS de um arquivo exceto a primeira;
# ainda deleta todas as linhas em branco do início e fim do arquivo (emula o
# "cat -s")
sed '/./,/^$/!d'          # método 1, permite 0 brancos no topo, 1 no
                          # final do arquivo
sed '/^$/N;/\n$/D'        # método 2, permite 1 branco no top, 0 no
                          # final do arquivo   
# deleta todas as linhas em branco do arquivo, exceto as 2 primeiras:
sed '/^$/N;/\n$/N;//D'
# deleta todas as linhas em branco iniciais, no início do arquivo
sed '/./,$!d'
# deleta todas as linhas em branco finais, no final do arquivo
sed -e :a -e '/^\n*$/N;/\n$/ba'
# deleta a última linha de cada parágrafo
sed -n '/^$/{p;h;};/./{x;/./p;}'

Criei um script ao qual dei o nome del_linhas, ele aceita um ou dois parâmetros quando se usar um só parâmetro ele apaga a linha fornecida pelo usuário, quando o script recebe dois parâmetros ele apaga do primeiro até o segundo. Outro detalhe sobre este scrip é que ele atua no diretório corrente.

1 #!/bin/bash
2 # Criado em:Qua 04/Jan/2006 hs 16:51
3 # ultima modificação: Qui 05 Jan 2006 10:13:51 BRST
4 # Apaga linhas
5 # Autor: Sérgio Luiz Araújo Silva 
6 
7  if [ "$#" -lt "2"  ]
8  then     # se for passado só uma linha
9      for i in `ls *`
10      do
11        echo "apagando a linha $1 do arquivo $i..."
12        cat $i | sed ${1}d > /tmp/$i
13        cat /tmp/$i > $i 
14        rm -f /tmp/$i
15      done
16  else     # se for passado um intervalo
17      for i in `ls *`
18      do
19        echo "apagando valo de $1 até $2"
20        cat $i | sed ${1},${2}d > /tmp/$i
21        cat /tmp/$i > $i 
22        rm -f /tmp/$i
23      done
24  fi 

Os fragmentos do scrip relevantes para o estudo do SED são (na linha 12)

sed ${1}d

e na linha 20

sed ${1},${2}d

Ambos usam variáveis e portanto não se usa aspas simples. A variável

${1}

É o primeiro parâmetro passado para o scrpt e a variável

${2}

É o segundo parâmetro passado para o script.

Script para geração de arquivos

Para estudar o sed fiz um scrip que cria 100 arquivos com a data atual
caso queira pode trocar o comando de data (date) por uma string qualquer por exemplo:

echo "string que será inserida no arquiovo"
#!/bin/bash
# Criado em:Seg 02/Jan/2006 hs 21:16
# ultima modificação: Qua 04 Jan 2006 18:16:10 BRST
# Script para criação de arquivos em série
# Autor: Sérgio Luiz Araújo Silva
# http://vivaotux.blogspot.com
#
# criação da data por extenso do tipo
# seguna 2 de janeiro de 2006
# trechos precedidos com "#" não são interpretados pelo bash
#
   dia_semana=`date +%A`
   dia_mes=`date +%d`
   mes=`date +%B`
   ano=`date +%Y`
   hora=`date +%T`
   dia_hoje=`echo "$dia_semana $dia_mes de $mes de $ano"`
#
# insira arquí o texto que vai ser colocado em cada arquivo
# se for usar aspas "  proteja com contra barra "\"
#
texto="Este deve ser usado para estudos diversos, experimente
usar o SED para fazer modificações em todos os arquivos de uma só
vez, visite a página do Aurélio \"http://aurelio.net/\" vá na seção
sobre o sed \"http://aurelio.net/sed/\". Não deixe também de visitar
o manual sobre Expressões regulares \"http://guia-er.sourceforge.net/guia-er.html\"
visite o site do Thobias ele é o mantenedor das funções zz criadas pelo Aurélio
a página do Thobias é: \"http://www.thobias.org/\" e as funções zz você
encontra em: \"http://funcoeszz.net/\"
e é claro visite meu blog: \"http://vivaotux.blogspot.com\"
outro bom site é Sed por exemplos:
\"http://geocities.yahoo.com.br/cesarakg/sed-1.html\"
\"http://geocities.yahoo.com.br/cesarakg/sed-2.html\"
\"http://geocities.yahoo.com.br/cesarakg/sed-3.html\"
Como o próprio nome diz, estes links dão acesso a uma página com
dezenas de exemplos práticos sobre a utilização do SED
Para exibir cada um dos arquivos gerados com numeração faça:
cat -n arquivo[1-100].txt, onde [1-100] é qualquer um dos 100
arquivos gerados pro este script."
#
# Coloque aquí o seu nome
   autor="Sérgio Luiz Araújo Silva"
# coloque aquí a extensão dos arquivos
   extensao=".txt"
# o laço propriamente de criação dos arquivos
   for ((i=1;i<=100;i++))
     do
       touch arquivo$i.txt
       echo " " >> arquivo$i$extensao #logo abaixo o cabeçalho
       echo " =====================================================" >> arquivo$i$extensao
       echo  "  Arquivo$i$extensao" >> arquivo$i$extensao
       echo  "  Criado $dia_hoje horas $hora" >> arquivo$i$extensao
       echo  "  Autor: $autor" >> arquivo$i$extensao
       echo  "  Arquivo para testes com SED ou egrep" >> arquivo$i$extensao
       echo  "  ou qualquer outro propósito, lhe convier!" >> arquivo$i$extensao
       echo " =====================================================" >> arquivo$i$extensao
       echo " " >> arquivo$i$extensao
       echo "$texto" >> arquivo$i$extensao # neste ponto insiro o texto
       echo " " >> arquivo$i$extensao
     done

Miscelânia

Para quem usa o vim há algumas configurações úteis a serem inseridas no .vimrc

Cria um cabeçalho para scripts bash

fun! InsertHeadBash()
   normal(1G)
   call append(0, "#!/bin/bash")
   call append(1, "# Criado em:" . strftime("%a %d/%b/%Y hs %H:%M"))
   call append(2, "# ultima modificação: " . strftime("%a %d/%b/%Y hs %H:%M"))
   call append(3, "# Autor: Sérgio Luiz Araújo Silva ")
   call append(3, "# Propósito do script")
   normal($)
endfun
map ,sh :call InsertHeadBash()<cr>A

Para chamar o mapeamento acima digite ,sh

Cria um registro de alterações de arquivo

" ChangeLog entry convenience
" Função para inserir um status do arquivo
" cirado: data de criação, alteração, autor etc
fun! InsertChangeLog()
   normal(1G)
   call append(0, "Arquivo")
   call append(1, "Criado: " . strftime("%a %d/%b/%Y hs %H:%M"))
   call append(2, "ultima modificação: " . strftime("%a %d/%b/%Y hs %H:%M"))
   call append(3, "Autor: Sérgio Luiz Araújo Silva")
   normal($)
endfun
map ,cl :call InsertChangeLog()<cr>A

Para chamar o mapeamento acima digite ,cl

Insere número de linhas no arquivo atual

map ,n :%s/^/\=line('.'). ' ' <cr>

Para chamar o mapeamento acima digite ,n
Lembre-se que a insereção do número de linhas é para o caso de enviar o script para análise, setar o número de linhas para ser exibido apenas é feito assim:

" o mapeamento abaixo coloca e retira a numeração
" o sistema alterna a numeração para ativa ou desativada (boleano)
map <F11> <esc>:set nu!<cr>


Veja mais sobre o vimrc em http://aurelio.net/doc/vim/

Veja Também

Horários baseados na GMT -3. Agora são 17:46.


Powered by vBulletin®
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd
SEO by vBSEO 3.2.0 ©2008, Crawlability, Inc.