« anterior | índice | próximo »

Estes são conhecimentos necessários àqueles que fazem uso intensivo do Sed, fazendo programas grandes e/ou complexos.

0.1. Monitorando um arquivo

No Sed da GNU, a partir da versão 3.02.80(*), foi adicionada a opção -u, que significa "unbuffered", ou seja, faz um uso minimalista dos registradores, mostrando a saída o mais rápido possível, tornando possível editar um fluxo interminável como o gerado por um tail -f.

Um exemplo prático seria mostrar apenas as mensagens do sistema relativas às conexões ssh:

prompt$ tail -f /var/log/messages | sed -nu '/sshd/p'

Cuidado com -nu perto de crianças! :)

(*) veja o tópico Nota sobre os adicionais GNU

0.2. Colocando comandos Sed num arquivo

Como os comandos Sed vão ficando extensos e complicados, é conveniente colocá-los num arquivo, com estruturação e comentários.

Você pode espalhar os comandos por várias linhas, trocando o ; por quebras de linha e colocar comentários precedidos de #. O exemplo de apagar linhas ficaria:

# programa.sed: apaga algumas linhas

# apaga a 5ª linha
5d

# apaga a 10ª linha
10d

# apaga as linhas que contêm 'estorvo'
/estorvo/d

Para dizer ao Sed para utilizar aquele arquivo como fonte de comandos, basta usar a opção -f

prompt$ sed -f programa.sed texto.txt

0.3. Tornando arquivos Sed executáveis

O interpretador de comandos mais utilizado (bash) sempre procura na primeira linha de um arquivo instruções para executá-lo.

Se um arquivo é um programinha em shell, basta colocar

#!/bin/sh

Na primeira linha para que o bash saiba que deve executá-lo com o comando /bin/sh. O mesmo funciona para qualquer outro interpretador, como o Sed. então para tornar um arquivos de comandos Sed executável basta colocar como primeira linha:

#!/bin/sed -f

E é claro, torná-lo executável:

prompt$ chmod +x programa.sed

E na linha de comando, chame-o normalmente:

prompt$ ./programa.sed texto.txt
prompt$ cat texto.txt | ./programa.sed

0.4. Conhecendo os registradores internos

0.4.1. Apresentação

O Sed possui 2 registradores ("buffers") internos, que são usados para a manipulação do texto.

Um deles é o espaço padrão ("pattern space"), que é o registrador utilizado normalmente pelo Sed. É nele que a linha a ser processada é armazenada e manipulada.

O outro é o espaço reserva ("hold space"), que é um registrador auxiliar, inicialmente vazio, que serve para guardar uma cópia da linha original, parte dela, ou agrupar dados diversos de várias linhas.

Há comandos para fazer a troca de dados entre os dois registradores:

  h      guarda no espaço reserva
  H      guarda (anexando) no espaço reserva

  g      pega o conteúdo do espaço reserva
  G      pega (anexando) o conteúdo do espaço reserva

  x      troca os conteúdos dos 2 registradores

O anexando acima significa "não sobrescreve o conteúdo original", ou seja, ele mantém o que já tem, e adiciona um \n (quebra de linha), seguido do texto manipulado. Para entender melhor, veja o exemplo gráfico a seguir.

0.4.2. Exemplo

Um exemplo didático de uso do espaço reserva é ir guardando nele algumas linhas do texto e mostrá-las depois no final do arquivo:

prompt$ sed '/root/H;$g' /etc/passwd

Ou seja, adicione no espaço reserva (comando H), as linhas que contêm a palavra root e na última linha do arquivo (endereço $), recupere o conteúdo do espaço reserva (comando g).

0.4.3. Exemplo gráfico

Como os registradores são a parte mais obscura do Sed (mais por falta de documentação do que por complexidade), merecem uma explicação bem didática. Vamos lá.

Temos os dois registradores vazios: (que daqui pra frente serão chamados apenas de padrão e reserva)

      __________________                __________________
     |                  |              |                  |
     |                  |              |                  |
     |__________________|              |__________________|
        espaço padrão                     espaço reserva

E um arquivo hipotético com o conteúdo: (não são odiosos estes exemplos com frutas?)

laranja
uva
abacaxi
melancia
mimosa

E aplicaremos o comando:

sed '/laranja/h ; /uva/g ; /abacaxi/H ; /melancia/G ; /mimosa/x'

Obtendo como resultado:

laranja
laranja
abacaxi
melancia
laranja
abacaxi
laranja
abacaxi

Vejamos o que aconteceu. Lida a primeira linha laranja, ela é imediatamente colocada no padrão para ser manipulada:

      __________________                __________________
     |                  |              |                  |
     |      laranja     |              |                  |
     |__________________|              |__________________|
        espaço padrão                     espaço reserva

O comando direcionado a ela é o h, que guarda uma cópia dela no reserva:

      __________________                __________________
     |                  |              |                  |
     |      laranja     |   -- h -->   |      laranja     |
     |__________________|              |__________________|
        espaço padrão                     espaço reserva

Como mais nenhum comando é relativo à linha laranja, o Sed dá por encerrado o processamento dessa linha e imprime o conteúdo do padrão na saída: "laranja".

Beleza, agora ele vai processar a segunda linha, novamente a primeira coisa é colocá-la no padrão, sobrescrevendo o que tinha antes:

      __________________                __________________
     |                  |              |                  |
     |        uva       |              |      laranja     |
     |__________________|              |__________________|
        espaço padrão                     espaço reserva

O reserva, enquanto nenhum outro comando escrever nele, permanecerá o mesmo. O comando direcionado à linha uva é o g, que pega o conteúdo do reserva e o coloca no padrão, apagando o que estiver nele (neste caso: uva):

      __________________                __________________
     |                  |              |                  |
     |      laranja     |   <-- g --   |      laranja     |
     |__________________|              |__________________|
        espaço padrão                     espaço reserva

Novamente, não há mais comandos a ser executados, então imprime na saída o conteúdo do padrão: "laranja".

Indo para a terceira linha e colocando-a no padrão:

      __________________                __________________
     |                  |              |                  |
     |      abacaxi     |              |      laranja     |
     |__________________|              |__________________|
        espaço padrão                     espaço reserva

O comando dessa linha é o H, que tal como o h, guarda o conteúdo do padrão no reserva, com diferença que ele preserva o conteúdo já existente dele, separando com um \n:

      __________________                __________________
     |                  |              |                  |
     |      abacaxi     |   -- H -->   | laranja\nabacaxi |
     |__________________|              |__________________|
        espaço padrão                     espaço reserva

Novamente, chegou ao fim, imprime o padrão: "abacaxi". a próxima linha é a da melancia:

      __________________                __________________
     |                  |              |                  |
     |     melancia     |              | laranja\nabacaxi |
     |__________________|              |__________________|
        espaço padrão                     espaço reserva

E agora vai ficar divertido, aplicando o comando G, que pega o conteúdo do reserva e anexa ao padrão:

 ____________________________           __________________
|                            |         |                  |
| melancia\nlaranja\nabacaxi |  <-G--  | laranja\nabacaxi |
|____________________________|         |__________________|
        espaço padrão                    espaço reserva

E a saída agora fica "melancia\nlaranja\nabacaxi", com o detalhe que o Sed troca estes \n por quebras de linha na impressão. Então são 3 linhas na saída. Vá acompanhando com o resultado que já foi cantado antecipadamente lá em cima.

E finalmente, a última linha:

      __________________                __________________
     |                  |              |                  |
     |      mimosa      |              | laranja\nabacaxi |
     |__________________|              |__________________|
        espaço padrão                     espaço reserva

E para ela, o comando que troca o conteúdo dos 2 registradores, o x:

      __________________                __________________
     |                  |              |                  |
     | laranja\nabacaxi |  <-- x --->  |      mimosa      |
     |__________________|              |__________________|
        espaço padrão                     espaço reserva

E mostra na saída o padrão, com duas linhas: "laranja" e "abacaxi".

Ufa! Depois dessa não venha me dizer que não sabe como funcionam os registradores internos do Sed ;)

0.4.4. Resumão

0.4.5. Fluxograma

Para uma representação gráfica dos fluxos e comandos que manipulam estes registradores, veja o tópico Fluxos dos registradores internos.

« anterior | índice | próximo »

Aprenda mais sobre Sed