Sed - Introdução

Introdução ao Sed, por meio de exemplos, cobrindo os tópicos: enviando dados pro sed, selecionando as linhas para edição, substituição, scripts em sed, expressões regulares, referências por &, back reference, hold space/ espaço reserva, dicas de comandos, jogos, exemplos e material para prosseguir nos estudos sobre Sed.

[ Hits: 84.845 ]

Por: jarlisson moreira em 16/07/2012


Referenciando com & - Back reference



Referenciando com &

Sempre que o sed casa algo, ele armazena esse algo em " & ".

Por exemplo: s/javali/porco/

Nesse caso: &=javali

Vamos usar o & para repetir cada número do "teste.txt":

cat teste.txt | sed 's/./&&/g'

" . " (ponto)-> Representa um único caractere. Como, no "teste.txt", cada linha possui somente um caractere, que é um número, o & armazenará o valor deste número, em cada linha.

Estamos substituindo um número (.), por ele duas vezes(&&).

Vamos para um exemplo prático. Vamos supor que você tem um site que pede o telefone do cliente, com DDD+número, sem parênteses ou hífens.

Crie: tels.txt

2134567890
8588887766
8599001122


Porém, exibir um número assim é confuso. Pra armazenar no seu banco de dados, OK. Mas para exibir isso pro cliente, não é interessante.

Então, vamos fazer um script em sed que pegue um ".txt" contendo telefones e transforme no padrão: (DDD)NUMEROS-NUMEROS

1. Vamos pegar os dois primeiros números e transformar neles envoltos de parênteses.

Para pegar os 2 primeiros números do início de cada linha:

's/^[[:digit:]][[:digit:]]/(&)/g'

Ou seja, o que vai casar, dois dígitos seguidos, fica armazenado na & e vamos colocar, no lugar desses dois números, isso (&). Mas é muito chato escrever [[:digit:]] duas vezes, pois, e se fossem 10 números e não só 2?

Para repetição, usamos o número de vezes que queremos repetir entre colchetes: {n}. No nosso caso, seria:

[[:digit:]]{2}

Vamos colocar isso no script, lembrando que temos que 'escapar' '{' e '}':

's/^[[:digit:]]\{2\}/(&)/g'

2. Depois de colocar os parênteses, devemos colocar um hífen após 4 dígitos.Como dizer isso pro sed? Simples.

Seja 'abcd' os números, queremos substituir isso por 'abcd-'. Mas não pode ser quatro números quaisquer, tem que ser os 4 dígitos após o parêntese " ) ".

Então, fica:

s/)[[:digit:]]\{4\}/&-/g

3. Lembrando que, o comando 2. só funciona se a substituição referente ao item 1, já tiver ocorrido. Ou seja, vamos colocar os comandos em sequência, e usaremos a flag '-e' para edições múltiplas.

O resultado é:

cat tels.txt | sed -e 's/^[[:digit:]]\{2\}/(&)/' -e 's/)[[:digit:]]\{4\}/&-/' > tels2.txt

E obtemos na "tels2.txt":
(21)3456-7890
(85)8888-7766
(85)9900-1122


Back reference

'&' só não é mais útil porque é só um.

No exemplo anterior, fizemos duas alterações no número. Imagine porém, se ao invés de duas, tivéssemos que fazer várias edições numa linha.

Faríamos " -e 's///' " várias vezes? Não, daria muito trabalho. Vamos usar back reference!

Coloque cada coisa que você quer casar entre parênteses. Ou seja, faça sua regex normalmente, mas ponha trechos dela entre parênteses. A cada trecho entre parênteses, o sed guarda o que foi casado em '\1', '\2', ..., em quantos trechos você tenha criado, para que você possa trabalhar com várias coisas que casaram, no mesmo comando.

Lembrando que para usar parênteses no sed, você tem que escapá-lo : \(\)

Vamos pegar o arquivo gerado no exemplo passado, o "tels2.txt", e explicitar mais cada trecho do telefone.

1. Código de área

O código de área é tudo que está do início até ')'. Como o analisador de linha do sed inicia no começo da linha, não é necessário explicitar isso, o ^ .

Veja: .*)

Colocando esse trecho entre parênteses(escapados) para depois referenciá-lo: \(.*)\)

Pronto. Se o sed achar um trecho do tipo: (nn), ele armazenará o que achar em '\1', onde 'n' é um caractere qualquer.

2. Primeira parte do número

São os quatro primeiros números do telefone, antes do hífen e depois dos parênteses.

Eles podem ser achados entre ')' e '-' . Porém, aqui tem um detalhe. Como anteriormente já casamos o trecho inicial (nn), a análise de linha do sed está localizada após o ')', pois vamos colocar tudo num comando só, como você verá mais à frente.

Portanto, não escrevemos: ).*-

E sim: .*-

Ou seja, catamos tudo, desde o ')', até o hífen.

Colocando entre parênteses, escapando: \(.*\)

Agora, os 4 primeiros números, fora o DDD, está em '\2'.

3. Agora, o analisador de linha do sed está localizado após o hífen e queremos pegar tudo do hífen até o final: .*$

Colocando entre parênteses e escapando: \(.*$\)

Esse trecho ficará em '\3'.

4. Agora vamos formatar a saída de modo a exibir uma mensagem bem mais detalhada sobre o telefone. Pra isso, colocamos tudo isso junto num 's///':

cat tels2.txt | sed 's/\(.*)\)\(.*-\)\(.*$\)/DDD: \1 Primeira parte: \2 Segunda parte: \3/g'

Note que pegamos tudo em sequência, de uma vez: primeiro o DDD, depois os 4 seguintes números e depois os 4 finais.

É como se nós tivéssemos usado o sed para dizer como é o formato do telefone: (nn)NUMERO-NUMERO

Como todos são neste formato, foi possível dividir em trechos: \1, \2 e \3

Isso só aconteceu graças à padronização dos dados.

E o resultado é:
DDD: (21)  Primeira parte: 3456-   Segunda parte: 7890
DDD: (85)  Primeira parte: 8888-   Segunda parte: 7766
DDD: (85)  Primeira parte: 9900-   Segunda parte: 1122


Página anterior     Próxima página

Páginas do artigo
   1. Introdução - o que é e para que serve
   2. Enviando dados para o sed
   3. Substituindo
   4. Scripts em sed
   5. Expressões regulares
   6. Referenciando com & - Back reference
   7. Hold space
   8. Por onde prosseguir e considerações finais
Outros artigos deste autor

LibreOffice Math

Pipelines (Canalizadores)

AWK - Introdução

Processos

Shell - Funções

Leitura recomendada

Pipelines (Canalizadores)

Debugando shell scripts

As maravilhas do Shell Script

Algoritmos em Shell Script

Linguagem Lua - Introdução ao Aprendizado da Linguagem

  
Comentários
[1] Comentário enviado por eldermarco em 16/07/2012 - 10:53h

Muito bom! Super bem escrito e bastante didático, exatamente como o artigo sobre o AWK que você escreveu. Nota 10!

[2] Comentário enviado por removido em 16/07/2012 - 12:42h

i like too!

[3] Comentário enviado por eduardo em 16/07/2012 - 14:13h

Ótimo artigo! Parabéns! Acabei de perceber que uso menos de 5% do poder do sed. :)

[4] Comentário enviado por sir.guil em 16/07/2012 - 15:05h

Parabéns, era uma coisa que faltava aqui no vol,

sempre que precisei estudar o sed, dependi do http://aurelio.net/sed/

agora estamos + completos

[5] Comentário enviado por julio_hoffimann em 16/07/2012 - 17:56h

Novamente parabéns Jarlisson!

Artigos bastante claros que ajudarão muitos no VOL.

Abraço!

[6] Comentário enviado por marcelo.castro.l em 17/07/2012 - 08:10h

Cara, muito bom esse artigo.
Salvou minha pátria aqui na empresa.
Precisava manipular um arquivo gerado pelo:

#iptables -L

Porém não precisava dele formatado com os espaços, graças ao "sed" tudo fluiu perfeitamente.

Obrigado!

[7] Comentário enviado por H4cktz em 19/02/2019 - 12:09h

Muito bom! Super bem escrito e bastante didático, Nota 1000! Finalmente estou aprendendo SED!


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts