Você está na página 1de 113

Escrevi este livro em 2002, entre os meses de Maro e Setembro.

uma obra
inacabada, que contm cerca de 60% do contedo planejado. Aps este perodo a
escrita parou e eu no tive mais vontade de continuar. A idia era fazer um guia
completo sobre o sed, uma bblia que abrangesse todos os tpicos, dando dicas
avanadas.

Hoje (Novembro de 2005) estou publicando o livro na Internet, com o texto intocado,
como parou em 2002. Considero este um trabalho que no deve ficar restrito ao meu
computador pessoal, pois mesmo incompleto pode ajudar outras pessoas a
dominarem o assunto.

Se voc novato em sed, leia o sed-HOWTO (http://aurelio.net/sed/sed-HOWTO)


primeiro. Terminada a leitura deste livro, domine tambm as Expresses Regulares
(http://aurelio.net/er) para obter o mximo do sed.

DIREITOS AUTORAIS (COPYRIGHT): Este contedo livre, voc pode reproduzi-lo


em qualquer meio, mas sempre deve citar a autoria (Aurlio Marinho Jargas) e o
endereo oficial http://aurelio.net/sed/livro.

Boa leitura!
ndice
Instalao..................................................................................................................7
Endereo...................................................................................................................9
Um endereo sempre aponta para uma linha inteira..........................................................11
Como enderear pelo nmero da linha................................................ ..............................12
Como enderear a primeira e/ou a ltima linha.................................................................13
Como enderear a linha que contm determinada palavra.................................................14
Como aplicar vrios comandos em um mesmo endereo...................................................17
Como enderear um trecho entre duas linhas, incluindo-as..............................................19
Como enderear um trecho entre duas linhas, excluindo-as..............................................21
Como negar um endereo, no aplicando comandos nele..................................................24
Como enderear a primeira ocorrncia de um padro........................................................26
Como enderear a primeira ocorrncia de um trecho.........................................................29
Como enderear a ltima ocorrncia de um padro...........................................................30
Como enderear a N-sima ocorrncia de um padro.......................................................34
Tem uma barra / no padro que procuro, e agora?............................................................35
Como usar outro delimitador fora a barra /......................................................................37
O que acontece com endereos invlidos..........................................................................40
E se eu colocar um endereo vazio como //?.....................................................................42
E se eu no colocar nenhum endereo?.............................................................................44
Detalhes srdidos sobre endereos.................................................. .................................45
Arquivo....................................................................................................................47
Como gravar o resultado num arquivo..............................................................................48
Como gravar o resultado no prprio arquivo original........................................................51
Como guardar os comandos sed num arquivo (script).......................................................56
Como utilizar um script sed........................................................ ......................................60
Como tornar executvel um script sed..............................................................................63
Como monitorar um arquivo com a ajuda do sed..............................................................66
Como ler o contedo de um arquivo.................................................................................68
Como gravar um trecho de texto num arquivo..................................................................74
Quebra de linha.......................................................................................................78
Como apagar uma quebra de linha, juntando duas linhas..................................................80
Como apagar todas as quebras de linha, deixando tudo numa s linha.............................82
Como fazer um lao.........................................................................................................84
Como fazer um lao com condicional de sada..................................................................85
Como fazer um lao com condicional de entrada..............................................................87
Como fazer um lao utilizando o reserva..........................................................................89
Como substituir alguma coisa por uma quebra de linha....................................................92
MAISCULAS/minsculas.........................................................................................93
Como deixar todo o texto em caixa alta (ou baixa)............................................................94
Como inverter a caixa de todas as letras...........................................................................98
Como levantar a caixa da primeira letra de cada linha.......................................................99
Como levantar a caixa da primeira letra de cada palavra..................................................103
Como ignorar a diferena de maisculas e minsculas....................................................106
Cumbuca...............................................................................................................109
Exemplos teis....................................................................... ........................................110
Emulando comandos UNIX/Linux....................................................................................111
Agradecimentos.....................................................................................................113
Dominando o SED - Instalao

Instalao
Antes de mais nada, o site http://sed.sf.net a fonte de informao mais atualizada sobre
onde encontrar o sed para as vrias plataformas suportadas. Consulte-o!

UNIX/Linux/Mac OS X

Espera a, voc vai me dizer que tem um UNIX/Linux e no tem sed instalado nele? Conta
outra! &:D

Para atualizar uma verso existente, o procedimento o mesmo do de outros programas, e


isso pode requerer a instalao de um RPM, um pacote .deb ou baixar um .tar.gz e compil-
lo.

Windows/DOS
Usurios de Windows tm duas opes para usar o sed:

SED.EXE no DOS
sed no Cygwin

7
Dominando o SED - Instalao

O sed nasceu no UNIX, mas vrias verses do programa foram feitas para MS-DOS devido
falta de uma ferramenta semelhante nesse sistema. O nome genrico SED.EXE, mas tambm
pode ser encontrado como SED.ZIP, caso acompanhe documentao.

A instalao no tem segredo. Basta copiar o arquivo SED.EXE para um diretrio que esteja no
PATH do seu MS-DOS. Lugares comuns so C:\Windows, C:\WIN ou C:\WINNT.

Para quem gosta de UNIX/Linux, aconselhvel instalar o Cygwin (http://aurelio.net/cygwin),


uma soluo completa com ferramentas UNIX que roda no Windows. Com um clique, voc tem
acesso a uma janelinha preta com sed, bash, cat, tr, grep, find, vi e dezenas de outros
programas. Vale conferir!

8
Dominando o SED - Endereo

Endereo
Prepare-se. Respire fundo. Abra sua mente para receber conceitos novos, empolgantes e
poderosos!

Para comear, deixemos claro que endereo no um comando, mas sim o seu contexto. o
elemento que diz exatamente em quais linhas um comando, ou bloco deles, dever ser
aplicado.

O QUE FAZER ---> comando


ONDE FAZER ---> endereo

O endereo algo simples se seus problemas forem simples. Mas quando se quer resolver
algo realmente cabeludo com sed, o endereo tambm pode se tornar um monstro, daqueles
que, de to feios, quem olha pensa: "Tomara que eu nunca precise fazer manuteno nisso".

Para facilitar, podemos fazer uma analogia com os endereos de nossas casas, compostos
por: nome da rua, nmero, cidade e CEP. O comando sed seria o carteiro que, baseado no
endereo escrito na carta, deve encontrar o local correto.

9
Dominando o SED - Endereo

Sabemos que quanto mais detalharmos o endereo, colocando todos os dados corretamente,
mais fcil para o carteiro encontrar o destino de nossa carta. Porm, na falta do CEP ou do
nmero da casa, a carta no chegar ao seu destino por causa do endereo incorreto.

No sed assim que acontece. Um endereo correto indispensvel para que o comando seja
aplicado no lugar certo. Assim, torna-se essencial para o programador, ao escrever um
comando sed, especificar o endereo com exatido e sem ambigidades.

O domnio do endereo diferencia os gurus dos gafanhotos

Faamos um mergulho profundo no assunto para dissecar todas as formas de utilizao e


conhecer as solues para os problemas mais rotineiros.

H trs tipos de endereos:

1. Endereo pelo nmero da linha


2. Endereo pelo contedo da linha
3. Endereo mltiplo, que abrange mais de uma linha

10
Dominando o SED - Endereo

Um endereo sempre aponta para uma linha inteira


A primeira coisa que deve ser assimilada sobre o conceito de endereo que ele sempre
referencia uma linha inteira, no somente parte dela. Afinal, sendo o sed um editor orientado
linha, o endereo no poderia ser diferente.

Ento, sempre que pensar em endereos, pense em linhas. Linhas inteiras.

Pode-se redefinir os trs tipos de endereo e ilustrar como cada um deles interpretado pelo
sed:

1. "Quero a linha nmero N"


2. "Quero a linha que contm a palavra ABCDE"
3. "Quero todas as linhas que estejam entre essas duas linhas"

11
Dominando o SED - Endereo

Como enderear pelo nmero da linha


A maneira mais simples de se determinar um endereo indicar diretamente sua posio no
arquivo, informando ao sed o nmero da linha qual se quer aplicar o comando. Por exemplo,
para apagar a 5 linha de um arquivo:

prompt$ sed '5 d' arquivo

Fcil, no? Observe que o espao em branco entre o endereo e o comando opcional, ento
tambm poderia ser 5d. Mas para facilitar a visualizao de quem quem, vamos separ-los
sempre.

E assim se enderea, numericamente, qualquer comando linha desejada, desde que se saiba
qual sua posio no arquivo.

12
Dominando o SED - Endereo

Como enderear a primeira e/ou a ltima linha


Para enderear a primeira linha, barbada: 1. Nada mais. Vamos apag-la?

prompt$ sed '1 d' arquivo

Moleza. Mas e a ltima? Nem sempre sabemos exatamente quantas linhas tem o arquivo, e
incmodo ter que usar outro programa para fazer isso antes de passarmos esse nmero ao
sed.

Para resolver esse problema, temos um caractere especial de endereo: o cifro $, que
representa a posio da ltima linha do arquivo. Ento fcil apagar a ltima linha:

prompt$ sed '$ d' arquivo

Note que em sistemas UNIX o uso das aspas simples obrigatrio. Sem elas o shell tentaria
expandir a varivel $d e o sed receberia um comando vazio.

13
Dominando o SED - Endereo

Como enderear a linha que contm determinada


palavra
Embora seja prtico e fcil enderear diretamente pelo nmero da linha, os problemas da vida
real nos mostram que nem sempre temos o privilgio de saber exatamente em qual linha
esto os dados procurados.

E quanto mais se trabalha com dados, mais se aprende que no bom confiar em posies
fixas porque elas raramente so fixas de verdade. Elas se mudam sem deixar telefone, email...
&:)

Tendo em vista estas necessidades, tambm podemos definir endereos que sejam palavras
ou trechos de uma linha.

Por exemplo, hoje no lanche comeremos frutas que... PRA! No odioso ter em livros
tcnicos esses exemplos "didticos" envolvendo bananas, mas e abacaxis? No repugnante
o autor tratar os leitores como crianas de primrio? Seus problemas acabaram! Nada de
exemplos com frutas por aqui.

Hoje, no lanche, comeremos verduras :) e como somos modernos e informatizados (nerds),


colocamos a lista de compras num arquivo.

14
Dominando o SED - Endereo

prompt$ cat verduras.txt


- alface
- cenoura
- couve
- nabo
- vagem

Mas, como hoje no um dia bom para comer couve, vamos apag-la da lista:

prompt$ sed '/couve/ d' verduras.txt


- alface
- cenoura
- nabo
- vagem

Note que, para especificar uma palavra como endereo, devemos coloc-la entre /barras/.
Dentro dessas barras, pode-se colocar qualquer padro que se queira casar para se encontrar
uma linha. Pode ser uma ou mais palavras, smbolos ou expresses regulares.

A melhor maneira de se ler um endereo composto por um padro : "Nas linhas que
contenham a palavra XXXX, aplique o comando YYYY".

Note bem: "naS linhaS".

15
Dominando o SED - Endereo

Um endereo pode servir para mais de uma linha, ento o comando ser aplicado em todas as
linhas que forem encontradas. Dessa forma, para apagar da nossa lista de verduras todas as
linhas que tenham a letra "o", fazemos:

prompt$ sed '/o/ d' verduras.txt


- alface
- vagem

Apenas como curiosidade, este exemplo gera um resultado idntico ao do comando:

prompt$ grep -v o verduras.txt

16
Dominando o SED - Endereo

Como aplicar vrios comandos em um mesmo


endereo
Agora que j sabemos quais so os dois tipos bsicos de endereo e como defini-los, vamos
comear a complicar um pouco o assunto.

Digamos que voc goste muito de couve, mas muito mesmo, e queira que ela aparea mais
trs vezes na lista de verduras. Teremos ento trs comandos a serem aplicados na mesma
linha:

prompt$ sed '/couve/ p ; /couve/ p ; /couve/ p' verduras.txt


- alface
- cenoura
- couve
- couve
- couve
- couve
- nabo
- vagem

Ficar repetindo o endereo para cada comando muito inconveniente. Utilizamos ento as
chaves {}, que nos permitem agrupar vrios comandos em um mesmo bloco. Este bloco
recebe um endereo, que ser usado por todos os comandos contidos nele.

17
Dominando o SED - Endereo

Nosso exemplo anterior fica assim:

prompt$ sed '/couve/{ p; p; p; }' verduras.txt

Preste ateno no seguinte detalhe: um bloco est sempre associado a um endereo, e a


chave de fechamento "}" como se fosse um comando do sed, devendo portanto ser separada
de outros comandos com ponto-e-vrgula ";".

Ao fechar o bloco, coloque sempre um ; antes da }

Sei que voc leu e entendeu, mas tenha absoluta certeza de que voc vai se esquecer desse
ltimo ";" vrias, diversas, milhares de vezes. &:)

18
Dominando o SED - Endereo

Como enderear um trecho entre duas linhas,


incluindo-as
Tudo ia bem na nossa vida de endereadores, at o dia em que precisamos enderear mais de
uma linha. Ou melhor, um trecho de texto entre duas linhas.

Por exemplo: como apagar da linha 5 linha 10 de um arquivo? Numa primeira tentativa,
afobada, a carreirinha

prompt$ sed '5d ; 6d ; 7d ; 8d ; 9d ; 10d' arquivo

... funciona. Mas e se quisssemos apagar 20 ou 30 linhas? Esse mtodo no prtico.

No sed, podemos especificar dois endereos, um de incio e outro de fim, para representar os
limites de um trecho entre duas linhas. Uma vrgula separa os dois endereos. Ento, a tarefa
anterior de apagar as linhas fica assim:

prompt$ sed '5,10 d' arquivo

Ou seja, da linha 5 at a linha 10, apague tudo. Lembre-se porm, que um endereo tambm
pode ser o cifro $ ou um padro. Ento agora podemos misturar todos os tipos de endereo.
Veja os exemplos:

19
Dominando o SED - Endereo

1,/couve/ da primeira linha at a linha que contm 'couve'


10,$ da linha 10 at o fim do arquivo
/couve/,$ da linha que contm 'couve' at o fim do arquivo
/couve/,/vagem/ da linha que contm 'couve' at a linha que contm 'vagem'
1,$ da primeira linha at a ltima (ou seja, todas)

Como pudemos notar, o trecho casado inclui as linhas de incio e fim do endereo. Se no era
este seu objetivo, veja o tpico seguinte.

20
Dominando o SED - Endereo

Como enderear um trecho entre duas linhas,


excluindo-as
No tpico anterior, vimos como enderear um trecho contendo vrias linhas e aprendemos
que limitam o trecho tambm so includas no endereo.

Mas, s vezes, queremos enderear apenas as linhas que esto dentro de um trecho,
excluindo as linhas delimitadoras de incio e fim. Nesse caso, precisamos de algo mais
elaborado.

Vamos usar um outro arquivo de exemplo, com os nmeros de um a seis por extenso:

prompt$ cat numeros.txt


um
dois
trs
quatro
cinco
seis

Supondo que se queira destacar tudo entre as linhas que contiverem um e cinco, incluindo as
prprias linhas delimitadoras, temos:

21
Dominando o SED - Endereo

prompt$ sed '/um/,/cinco/ s/^/---/' numeros.txt


---um
---dois
---trs
---quatro
---cinco
seis

Mas, se quisermos excluir as linhas delimitadoras, devemos trat-las individualmente, dentro


de um bloco:

prompt$ sed '/um/,/cinco/ { /um/ b ; /cinco/ b ; s/^/---/ ; }' numeros.txt


um
---dois
---trs
---quatro
cinco
seis

Mais detalhadamente:

/um/,/cinco/ { ;# entre a linha 'um' e a linha 'cinco' ...


/um/ b ;# se for a linha 'um', salte para o fim do script e
;# processe a prxima linha (ou seja, no faa nada nesta)
/cinco/ b ;# se for a linha 'cinco', salte para o fim do script e
;# processe a prxima linha (ou seja, no faa nada nesta)
s/^/---/ ;# nos outros casos, coloque '---' no comeo da linha
}

22
Dominando o SED - Endereo

Ento, o comando b sozinho funciona como um pulo, uma exceo que no deixa o
processamento chegar at o s/^/---/ nas linhas especificadas.

23
Dominando o SED - Endereo

Como negar um endereo, no aplicando comandos


nele
Assim como podemos definir um endereo para aplicao de um comando, tambm podemos
determinar que um comando no seja aplicado nesse endereo, ou seja, que o comando se
aplica a todas as linhas menos aquela. Veja como apagar todas as linhas do arquivo menos a
linha 5:

prompt$ sed '5! d' arquivo

O modificador de endereo ! o responsvel pela inverso, e essa lgica s avessas pode


confundir. Uma leitura desse comando poderia ser: "Na linha 5, no a apague".

Para facilitar o entendimento correto de sua funo, leia o comando de maneira inversa,
usando a palavra "exceto" ou "menos". Assim: "Apague TODAS as linhas EXCETO a linha 5".

O mesmo vale para um bloco de comandos e para um endereo duplo:

/padro/! { p; d; }

/padro1/,/padro2/! { p; d; }

24
Dominando o SED - Endereo

Com blocos, a leitura fica: "Aplique os comandos do bloco em TODAS as linhas EXCETO as do
endereo".

Assim sendo, fica fcil mostrar apenas um trecho de texto e apagar todo o resto:

prompt$ sed '/dois/,/cinco/! d' numeros.txt


dois
trs
quatro
cinco

Em outro exemplo, vamos emular o comando head do UNIX, que imprime as 10 primeiras
linhas de um arquivo. Uma das possibilidades seria esta:

sed '11,$ d' apague da linha 11 at o fim do arquivo

Ou ento, usando o modificador !, podemos inverter a lgica e fazer assim:

sed '1,10! d' apague todas as linhas EXCETO da linha 1 at a 10

Pode parecer estranho (e !) pensar invertido, mas voc se acostuma &:)

25
Dominando o SED - Endereo

Como enderear a primeira ocorrncia de um padro


Como j vimos, o endereo pode servir para mais de uma linha. Aps encontrar a primeira
ocorrncia do padro e executar o comando, o sed continua lendo o arquivo. O comando
ento ser novamente aplicado em todas as outras linhas em que o padro for encontrado.

Mas, e para enderear apenas a primeira ocorrncia do padro e no as restantes?

Aqui, precisamos de um pouco de criatividade. A idia especificar uma "rea de atuao"


para o comando, para que seu endereo somente seja vlido nesta rea.

Para nosso objetivo, a rea deve comear no incio do arquivo e ir at a primeira linha onde o
padro for encontrado. Ei, j sabemos como fazer isso, basta enderear!

1, /padro/ { comandos ; }

Usando a linha 1 como primeiro endereo, conseguimos "ancorar" o bloco de comandos no


incio do arquivo. Dessa maneira garantimos que apenas a primeira ocorrncia do padro est
contida neste endereo.

Definida nossa rea de atuao, agora ficou fcil! Por exemplo, para modificar somente a
primeira linha que contenha a letra "o" no nosso arquivo de nmeros:

26
Dominando o SED - Endereo

prompt$ sed '1,/o/{ /o/ s/^/---/ ; }' numeros.txt


um
---dois
trs
quatro
cinco
seis

Vamos ler este comando: "Dentro da rea que vai da primeira linha at a linha que conter a
letra 'o', faa: se for uma linha com 'o', adicione '---' no comeo".

H tambm uma ttica mais simples, que funciona em casos especficos. Para tarefas como
extrao de dados, onde se busca apenas a primeira ocorrncia e nada mais, o comando de
interrupo de processamento pode ser utilizado.

A idia simples: colocar num bloco o comando desejado e a interrupo. Como a interrupo
s pode ser executada uma vez, est feito nosso "condicional" para obter apenas o primeiro.

Exemplo: extrair do arquivo apenas a primeira linha com a letra "o":

prompt$ sed -n '/o/{ p; q; }' numeros.txt


dois

Com a opo -n, silenciamos a sada do sed. Na linha com "o", executado um Print para
mostr-la e um Quit para sair.

27
Dominando o SED - Endereo

A mesma ttica utilizada para extrair os cabealhos de um e-mail, que ficam sempre no
incio, separados do corpo da mensagem por uma linha em branco:

sed '/^$/q' email.txt

Traduzindo: "Ao encontrar a primeira linha em branco do arquivo, saia".

28
Dominando o SED - Endereo

Como enderear a primeira ocorrncia de um trecho


Um endereo duplo tambm est sujeito s mesmas regras de um endereo normal, ento um
trecho de texto pode se repetir vrias vezes e o seu comando (ou bloco) ser executado tantas
vezes quantas necessrias.

Assim sendo, o comando /(/,/)/ d apagar TODOS os trechos do texto que estiverem
delimitados por parnteses, podendo o parntese que fecha estar numa linha diferente do que
abre.

Para limitar esse endereo ao primeiro trecho encontrado, usamos a mesma ttica de
ancoragem com a primeira linha usada no tpico anterior:

1,/)/ {
/(/,/)/ d
}

Traduzindo: "Do comeo do texto at a primeira linha que contiver ')', apague tudo que estiver
entre os parnteses, inclusive eles prprios".

29
Dominando o SED - Endereo

Como enderear a ltima ocorrncia de um padro


Entramos agora num tpico complexo. Enderear a primeira ocorrncia de um padro ou
trecho algo relativamente fcil. Mas a ltima no to simples:

prompt$ sed '/o/,${ /o/ d ; }' numeros.txt


um
trs
seis

A tentativa bvia falha porque o sed l as linhas de cima para baixo, ento o endereo
especificado acaba significando: "Procure da primeira linha que tiver a letra 'o' at a ltima
linha do texto".

Para fazermos um s/primeira/ltima/ com este significado, temos algumas alternativas. A mais
fcil, porm exclusiva de quem possui o comando tac, que imprime um arquivo da ltima para
a primeira linha, pode ser:

prompt$ tac numeros.txt


seis
cinco
quatro
trs
dois
um

30
Dominando o SED - Endereo

prompt$ tac numeros.txt | sed '1,/o/{ /o/ d ; }' | tac


um
dois
trs
quatro
seis

Ento, invertendo a ordem das linhas, aplicamos o mesmo conceito de ancorar pela primeira
linha do arquivo (que na verdade a ltima), e ento basta desinverter o arquivo aplicando tac
novamente.

Quem no possui o tac, pode emul-lo com o sed:

prompt$ sed '1! G ; h ; $! d' numeros.txt


seis
cinco
quatro
trs
dois
um

E trocando o tac do comando anterior por este em sed, ficamos com:

sed '1!G;h;$!d' numeros.txt | sed '1,/o/{ /o/ d ; }' | sed '1!G;h;$!d'

31
Dominando o SED - Endereo

Feio, muito feio. E esse mtodo de inverso complica tudo, pois o script a ser aplicado ao
trecho, caso seja necessrio mexer com mais de uma linha, tambm precisa trat-las de
maneira invertida. Em algumas situaes onde se tem uma seqncia certa de linhas, inverter
a lgica pode ser impraticvel.

Mas, com exceo dessa ttica, no h muitas alternativas. Dependendo do que precisamos
fazer com o padro, podemos usar outras abordagens.

Por exemplo, se precisarmos simplesmente imprimir na tela a linha da ltima ocorrncia,


podemos usar o sed duas vezes:

prompt$ sed '/o/! d' numeros.txt | sed '$! d'


cinco

O primeiro obtm todas as linhas que contm o padro, e o segundo mostra apenas a ltima
linha, apagando todas as outras. Um comando UNIX similar seria:

prompt$ grep 'o' numeros.txt | tail -1

Para fazer isso usando apenas um sed, podemos utilizar o RESERVA para ir armazenando
(sobrescrevendo) todas as linhas que contm o padro, e quando chegarmos na ltima linha
do arquivo, mostramos o contedo do RESERVA:

32
Dominando o SED - Endereo

prompt$ sed '/o/ h ; $! d ; $ g' numeros.txt


cinco

Para entender melhor:

/o/ h ;# guarde (sobrescrevendo) no RESERVA as linhas que contm 'o'


$! d ;# apague todas as linhas, menos a ltima
$ g ;# se for a ltima linha, pegue o contedo do RESERVA

Infelizmente, no h uma "receita de bolo" para enderear de maneira genrica a ltima


ocorrncia. Cada caso um caso, e merece uma soluo personalizada.

33
Dominando o SED - Endereo

Como enderear a N-sima ocorrncia de um padro


Fazendo magia negra. :)

J vimos como complicado enderear a ltima ocorrncia do padro, e no h como fazer


isso de maneira genrica. Agora imagine especificar uma posio arbitrria de repetio de
um padro.

Caso seja algo simples, como s mostrar na tela a terceira linha que contenha a letra "o", por
exemplo, podemos usar a ttica anterior de usar o sed duas vezes:

prompt$ sed '/o/! d' numeros.txt | sed '3! d'


cinco

Sim, possvel, dependendo do caso. Mas contando que o grau de dificuldade enorme para
se fazer isso num problema mais elaborado, alm do cdigo resultante ficar grande e difcil de
se manter, o aconselhvel usar outra linguagem, como awk, que tem o conceito de linhas e
registros, incluindo contadores, ou usar o sed em conjunto com um script shell.

Como nem um (shell) nem outro (awk) faz parte do nosso tpico, fim de papo.

34
Dominando o SED - Endereo

Tem uma barra / no padro que procuro, e agora?


Ao procurar linhas com datas, nomes de diretrios, ou outros padres que possuem o
caractere "/" podemos nos surpreender com as mais diversas mensagens de erro:

prompt$ sed '//tmp/lixo.bmp/ d' arquivo


sed: -e expresso #1, caractere 2: no h uma expresso regular anterior

prompt$ sed '/tmp/lixo.bmp/ d' arquivo


sed: -e expresso #1, caractere 7: h caracteres sobrando aps o comando

prompt$ sed '/31/12/2000/ d' arquivo


sed: -e expresso #1, caractere 5: comando desconhecido: `1'

As mensagens de erro do sed so em geral curtas e esclarecedoras, mas no caso de problema


com o delimitador, elas ficam especialmente obscuras. Anote em algum canto de seu crebro:

Se a mensagem de erro do sed aliengena, confira os delimitadores.

O que aconteceu em todos os exemplos que o sed confundiu a barra normal dos padres
com a barra delimitadora do endereo. O que temos que fazer aqui para que essas barras
normais no sejam interpretadas como delimitadoras, escap-las.

35
Dominando o SED - Endereo

Segundo o Aurlio (o outro), um dos significados de escapar "passar despercebido". E


exatamente isso o que precisamos: fazer com que a barra no seja considerada especial pelo
sed. Quem faz esta mgica a barra invertida "\", que colocada antes de um caractere normal,
o escapa, impedindo que o sed o considere um delimitador de endereo.

Em nosso caso, a barra "/" escapada fica: \/. Como dica geral, sempre escape as barras
normais do padro, evitando dores de cabea.

Mas vamos voltar aos exemplos anteriores, agora com as barras devidamente escapadas:

prompt$ sed '/\/tmp\/lixo.bmp/ d' arquivo


prompt$ sed '/tmp\/lixo.bmp/ d' arquivo
prompt$ sed '/31\/12\/2000/ d' arquivo

Note que so escapadas apenas as barras internas, as barras delimitadoras do endereo


continuam as mesmas.

36
Dominando o SED - Endereo

Como usar outro delimitador fora a barra /


Agora c entre ns, esse negcio de ficar escapando barras no nem um pouco prtico. Pior
ainda se nosso padro estiver dentro de uma varivel, e no for to visvel o conflito de
barras, como em sed "/$PWD/ d", onde $PWD contm o diretrio atual de trabalho.

Para esses e outros possveis problemas, o sed nos d a liberdade de escolher qualquer
caractere da tabela ASCII como delimitador de endereo.

Ento como regra geral para escolher qual smbolo usar, utiliza-se um delimitador que se tem
certeza que no vai ser confundido com nenhum caractere do padro a ser procurado.

O nico porm para usar algo diferente da barra /, que precisamos dizer ao sed: "Ei, o
prximo caractere aqui vai ser o delimitador". Para isso, basta escapar o primeiro (somente o
primeiro!) delimitador, assim:

sed '\,31/12/2000, d' arquivo

Ento utilizamos a vrgula como delimitador de endereo, escapando a primeira para que o
sed a veja como especial.

37
Dominando o SED - Endereo

Delimitador: escolha qualquer ASCII, escape o primeiro

Fora a vrgula, outros delimitadores reserva que so clssicos de usar a barra vertical |, o
arroba @ e a exclamao !. Agora, para evitar dor de cabea e usar um delimitador que
dificilmente coincidir com qualquer padro, use caracteres esquisitos como: , e .

Ou ainda, se voc quiser fazer algo realmente esquisito, use caracteres brancos como o
espao ou o TAB, ou letras normais do alfabeto, nmeros (cuidado!)

sed '\ 31/12/2000 d' arquivo

sed '\i31/12/2000i d' arquivo

sed '\831/12/20008 d' arquivo

Ou pior ainda, at a quebra de linha pode ser usada!

prompt$ sed '\


> 31/12/2000
> d' arquivo

Quem disse que o sed no divertido? &:)

38
Dominando o SED - Endereo

Uma regra boa para a escolha do delimitador, alm dele no coincidir com algum caractere do
padro, que ele seja visualmente oposto ao padro. Isso quer dizer que se o seu padro
tiver uma predominncia de caracteres altos, como uma palavra em MAISCULAS,
aconselhvel usar caracteres baixos como delimitadores, como a vrgula, dois pontos e o
sublinhado. E se o padro for predominantemente baixo, caracteres como / ! | % e @ so mais
indicados. Veja:

visual confuso
s_$PWD_/TMP_ s!$PWD!/TMP!
s|...=|=| s:...=:=:

39
Dominando o SED - Endereo

O que acontece com endereos invlidos


Um endereo invlido pode ser uma palavra que no encontrada em nenhum lugar no texto,
ou uma linha que no existe, por exemplo a linha 20 num arquivo que s possui 15 linhas.

E agora a dvida que assola a humanidade: "E se eu colocar um endereo invlido?" a resposta
: depende.

Se for um endereo simples de uma linha, o comando simplesmente no vai ser executado,
pois nenhuma linha satisfez o padro.

Se for um endereo de um trecho entre duas linhas, o resultado diferente caso o endereo
invlido seja o primeiro ou o segundo. Vamos acompanhar um exemplo utilizando a palavra
prego como padro no nosso arquivo de verduras:

prompt$ sed '/prego/,$ d' verduras.txt


- alface
- cenoura
- couve
- nabo
- vagem
prompt$ sed '1,/prego/ d' verduras.txt
prompt$

40
Dominando o SED - Endereo

No primeiro exemplo, era para apagar da linha que tivesse prego at o final. Como nenhuma
linha tinha prego, o primeiro endereo falhou e nada foi apagado.

J no segundo exemplo era para apagar da primeira linha at a linha que tivesse prego. A
primeira linha foi encontrada, ento o comando d vai ser aplicado at achar o segundo
endereo. Mas como no tem prego no arquivo, o comando vai sendo aplicado at bater na
ltima linha. como dizer: "Ningum me mandou parar, ento continuei".

1 endereo invlido: endereo invlido, nada acontece


2 endereo invlido: endereo incompleto, vai at o final

41
Dominando o SED - Endereo

E se eu colocar um endereo vazio como //?


Um endereo vazio referencia o ltimo endereo pesquisado.

Essa uma funcionalidade muito til e que pode poupar muita redundncia no endereo.

Lembra do exemplo de imprimir mais trs vezes a linha da couve?

prompt$ sed '/couve/ p ; /couve/ p ; /couve/ p' verduras.txt

Esse comando poderia ser reescrito assim:

prompt$ sed '/couve/ p ; // p ; // p ' verduras.txt

E aquele outro de ancoragem para imprimir apenas a primeira linha que contivesse a letra o?

prompt$ sed '1,/o/{ /o/ d ; }' numeros.txt

Este pode ficar assim:

prompt$ sed '1,/o/{ // d ; }' numeros.txt

42
Dominando o SED - Endereo

A diferena parece pequena porque os exemplos usam endereos bem simples, mas quando
eles so monstros gigantes que cospem expresses regulares, o endereo vazio ajuda muito.

E tem ainda o clssico //s/// que um comando vlido e bem utilizado. Voc se arrisca a
adivinhar o que ele faz?

43
Dominando o SED - Endereo

E se eu no colocar nenhum endereo?


O comando serve para todas as linhas. Ponto.

prompt$ sed 'd' verduras.txt


prompt$

44
Dominando o SED - Endereo

Detalhes srdidos sobre endereos


Apesar de os tpicos anteriores esmiuarem vrios aspectos do endereo, ainda restam alguns
detalhes que devem ser assimilados.

Os nicos comandos que no recebem endereo so o : e o }, ambos por serem


comando relativos a posies do prprio script e no do texto que est sendo
processado.

Os comandos que no recebem dois endereos so =, a, i, q e r, pois s podem ser


aplicados a apenas uma linha por vez. Mas se diretamente no conseguimos endere-
los a um trecho como em 1,5=, usando blocos no h problema: 1,5{ =; }

Os comandos que devem receber endereo so ! e {. O ! por ser um inversor de


endereos, aplicando o comando exceto no endereo indicado e o { que define um
bloco de comandos a ser aplicado no endereo especificado. Se no tiver endereo, o
bloco ser aplicado para todas as linhas tornando desnecessrio o agrupamento.

As linhas de incio e fim de um trecho no podem ser a mesma linha, ento mesmo que
seu endereo tenha padres idnticos como /cebola/, /cebola/, sero necessrias duas
linhas diferentes que contenham a palavra cebola para que este endereo seja
encontrado. Ento um trecho sempre tem no mnimo, duas linhas.

45
Dominando o SED - Endereo

O \n como identificador de quebra de linha no endereo s vlido aps a aplicao do


comando N, que gruda linhas no PADRO separando-as pelo \n. Do contrrio, no
haver mais de uma linha no PADRO para se processar.

46
Dominando o SED - Arquivo

Arquivo
J vimos que o sed no um editor de arquivos, mas de fluxos de texto. Como tal, a sua
funo aplicar os comandos de edio no texto e mostrar o resultado na tela.

Mas mesmo tendo seu funcionamento independente do conceito de arquivos, o sed precisa
lidar com eles, pois ns humanos gostamos de arquivos!

Temos nossos dados guardados em arquivos, ento o sed precisa ter a capacidade de ler e
gravar linhas em arquivos. Podemos ainda querer guardar todo o resultado da edio feita
pelo sed em um arquivo. Ou ainda, podemos querer colocar nossos comandos sed num
arquivo, pois eles esto ficando muito complicados. Feito isso, podemos at torn-lo um
arquivo executvel, que chama o sed automaticamente para interpret-lo!

Ufa! Para um programa que edita somente fluxos de texto, at que temos vrios detalhes para
ver no assunto "Arquivo", no? &:)

47
Dominando o SED - Arquivo

Como gravar o resultado num arquivo


Apesar do sed ter sido concebido como um filtro, que repassa o fluxo de texto para a tela do
computador, ns usurios tambm temos necessidades de armazenamento desse fluxo.

Seja para consulta posterior, para edio de arquivos (e no fluxos) ou para registros e
extrao de dados, importante guardamos o texto processado pelo sed em um arquivo.

Mas sendo o sed um filtro de fluxos, o que ele entende de arquivos? Quase nada. Por isso a
soluo desse problema est um pouco mais embaixo, no shell, que o ambiente onde o sed
executado.

A tela chamada de "sada padro" do sed, o caminho natural que o fluxo segue aps ser
processado. Mas como essa sada passa tambm pelo shell antes de ir para a tela, ele tem
meios de "desvi-la" e mand-la para um arquivo. Esse desvio chamado de
"redirecionamento", e o caractere utilizado para represent-lo o maior-que ">".

Informatiqus: Precisamos redirecionar a sada padro!

48
Dominando o SED - Arquivo

Ento aplicamos os comandos sed desejados no texto e redirecionamos o resultado dessa


edio para um arquivo:

prompt$ sed 'comandos' texto.txt > texto-alterado.txt

Este redirecionamento chamado destrutivo, pois caso j exista o arquivo texto-alterado.txt,


ele ser "truncado". Truncar em informatiqus significa cortar, apagar, excluir, remover,
limpar, zerar, ou seja, o contedo anterior do arquivo ser perdido. Caso o arquivo ainda no
exista, o shell o criar.

A outra opo usar o redirecionamento incremental, representado por dois sinais de maior-
que ">>". Ao contrrio do destrutivo, se o arquivo j existir, seu contedo original ser
preservado e o texto novo ser anexado aps a ltima linha. Caso o arquivo ainda no exista,
o shell o criar.

prompt$ sed 'comandos' texto.txt >> texto-alterado.txt


prompt$ sed 'outros-comandos' texto.txt >> texto-alterado.txt

Memorizar fcil!

49
Dominando o SED - Arquivo

Usando... ...acontece
> o arquivo sempre zerado
>> o arquivo vai crescendo, crescendo...

A maioria dos ambientes shell conhecidos utiliza a notao do > e >> para redirecionamentos,
aqui vo alguns deles:

no UNIX/Linux: sh, ash, bash, ksh


no Macintosh: MPW Shell
no Windows: MS-DOS

50
Dominando o SED - Arquivo

Como gravar o resultado no prprio arquivo original


Olhe ali para aquela cmera, voc acaba de cair na pegadinha de gravar no mesmo arquivo!

Quem nunca apagou um arquivo importante para descobrir que o UNIX/Linux no tem
undelete nem "Lixeira"?
Quem nunca perdeu um HD inteiro para descobrir a importncia do becape?
Quem nunca apertou o boto "Ok" na mensagem "Deseja sair sem salvar as alteraes?"
e teve que redigitar o documento?
Quem nunca deu um rm -rf / tmp/lixo ou um rm -rf * .txt ou um rm -rf .* ?

Pois amigo, brincadeiras parte, fazer cacas irreversveis em informtica to fcil que uma
simples apertada na tecla Enter na hora errada pode destruir um dia de trabalho (ou vrios...).

Essa introduo descontrada serve para aliviar o peso da culpa daqueles que j descobriram
pelo jeito difcil que gravar o resultado no mesmo arquivo pode ser cruel &:)

51
Dominando o SED - Arquivo

Problema inicial

Como j visto, utiliza-se o redirecionamento do shell para gravar o resultado do sed num
outro arquivo. Mas muito comum ao se editar um determinado arquivo, querer gravar estas
alteraes no prprio arquivo original. Faz sentido no faz? Ento a tentativa bvia e intuitiva
o clssico tiro no p:

prompt$ sed 'comandos' texto.txt > texto.txt

Alm de no dar certo, todo o contedo original do arquivo ser perdido. Que dureza hein?
Mas se errando que se aprende, caso voc nunca tenha feito essa caquinha (ainda), agora
sua chance de aprender sem precisar sofrer.

O que ocorre que ao fazer o redirecionamento destrutivo >, a primeira coisa que o shell faz
truncar o arquivo referenciado, antes mesmo de comear a executar o sed. Ento o contedo
do arquivo ser apagado antes do sed poder l-lo.

Quando finalmente o sed for chamado pelo shell, receber um arquivo vazio, e a no d para
fazer mgica: aplicados quaisquer comandos num arquivo vazio, o resultado ser sempre um
arquivo vazio. E fim de papo.

52
Dominando o SED - Arquivo

Soluo genrica

Para solucionar este dilema, voltamos a ttica j conhecida de redirecionar o resultado para
um outro arquivo, e depois mover o arquivo novo sobre o original:

prompt$ sed 'comandos' texto.txt > texto-alterado.txt


prompt$ mv texto-alterado.txt texto.txt

Para a grande maioria dos casos, isso suficiente. Porm caso as caractersticas do arquivo
original devam ser mantidas, temos um problema.

Como acabamos de criar um arquivo novo para guardar o texto alterado, ele ter os atributos
padro do sistema. Ao mov-lo sobre o arquivo original, estes atributos padro sero
herdados.

Atributos especiais que o arquivo original pudesse ter como: grupo diferente do padro do
usurio, permisses especficas (rwx) ou referncias para outros arquivos (links, simblicos ou
no) sero perdidos.

Soluo segura

Para uma soluo prova de falhas, usa-se uma abordagem mais conservadora e segura:
copiar o arquivo e redirecionar a sada para o original.

53
Dominando o SED - Arquivo

A primeira ao a se fazer copiar o arquivo original para um arquivo temporrio qualquer.


Feito isso, ento se aplica os comandos sed neste temporrio. Agora vem o pulo do gato:
redireciona-se a sada do sed para o arquivo original:

prompt$ cp texto.txt texto-tmp.txt


prompt$ sed 'comandos' texto-tmp.txt > texto.txt

Dessa maneira no estamos criando um arquivo texto.txt novo, mas apenas trocando o seu
contedo, permanecendo inalteradas as suas caractersticas no sistema. Para finalizar a
operao, basta apagar o arquivo temporrio.

prompt$ rm texto-tmp.txt

importante ter em mente a importncia desta abordagem segura e o porqu de utiliz-la.


No apenas para o sed, mas tambm para outros comandos do sistema que atuam como
filtros, mandando o resultado para a tela.

Soluo moderna

Para evitar todas essas preocupaes e no ter que criar um arquivo temporrio, algumas
verses do sed (FreeBSD, ssed, gsed-4) possuem a opo "-i", que aplica os comandos "in-
place", ou seja, no mesmo arquivo.

54
Dominando o SED - Arquivo

Dessa forma, no se depende mais do shell para contornar a situao:

prompt$ sed -i 'comandos' texto.txt

55
Dominando o SED - Arquivo

Como guardar os comandos sed num arquivo (script)


medida que vamos evoluindo no aprendizado, os comandos sed vo ficando cada vez mais
extensos e complicados. Ficar sempre redigitando tudo na linha de comando torna-se um
incmodo. Seria interessante poder guardar os comandos num arquivo!

Nesse momento em que sentimos a necessidade de algo mais prtico, presenciamos nossa
prpria evoluo, a passagem da infncia para a adolescncia no aprendizado do sed. Ao
invs de fazer um "comando sed", agora vamos fazer um "script sed", com bastante comandos
e estruturado. Na fase adulta de aprendizado, podemos ainda evoluir para um "programa sed",
que ao invs de editar textos, os domina.

O simples fato de colocar os comandos sed num arquivo ao invs de digit-los na linha de
comando, muda alguns aspectos da brincadeira divertida de manipular texto. Vamos aos
detalhes srdidos!

A primeira vantagem que no precisamos mais nos preocupar com o shell, tendo que
proteger os comandos entre aspas para no serem confundidos e interpretados. Dentro do
arquivo podemos colocar quaisquer caracteres, despreocupadamente.

56
Dominando o SED - Arquivo

Mas no mesmo ponto que temos a primeira desvantagem: perdemos o contato com o shell,
nosso aliado poderoso. Com suas variveis, operaes e comandos, o shell complementa
onde o sed limitado. Quando colocamos os comandos sed num arquivo, eles tornam-se
estticos, e a interatividade direta com o shell perdida.

Uma outra vantagem da utilizao do arquivo, que podemos separar melhor os comandos,
colocando um em cada linha. Podemos fazer inclusive o alinhamento estruturado
("indentation") para que os blocos de comandos fiquem mais visuais.

E mais, agora podemos colocar tambm comentrios! Desprezado por muitos, eles so uma
das partes mais importantes de um programa. S quem j precisou dar manuteno num
cdigo complexo e sem comentrios (ou mal comentado) sabe a falta que eles fazem...

E por favor, pelo seu prprio bem e dos que um dia precisarem dar manuteno num script
sed de sua autoria, encha-o de comentrios! O sed especialmente abstrato e desafiador,
com seus comandos de apenas uma letra, sem variveis e muitas expresses regulares. A falta
de comentrios pode deixar um script inutilizvel se ningum souber como atualiz-lo. O
caractere que precede os comentrios num script sed aquele que cada um chama de um
jeito: #. Gradinha, cerquilha, sustenido, jogo da velha, hash, ...

Script sed: shell--, alinhamento++, comentrios++, legibilidade++

57
Dominando o SED - Arquivo

Vamos relembrar o exemplo de enderear entre duas linhas, excluindo-as:

prompt$ sed '/um/,/cinco/ { /um/ b ; /cinco/ b ; s/^/--- / ; }' numeros.txt

um endereo com um bloco de comandos dentro das chaves {}. No bloco esto trs
comandos, separados por ponto-e-vrgula. H uma certa dificuldade em identificar e entender
as partes desse comando, por estar tudo misturado numa nica linha. Vamos coloc-lo num
arquivo e ver se melhora?

### meu primeiro script sed


# ei, isso um comentrio!

# vamos delimitar um bloco de linhas


# endereo: entre a linha que contm 'um' e a linha que contm 'cinco'
/um/ , /cinco/ {

### nesse ponto do script, s chegaro as linhas que estiverem entre


### 'um' e 'cinco', incluindo elas prprias.

# se for a linha que contm 'um', v at o final do script


/um/ b

# se for a linha que contm 'cinco', v at o final do script


/cinco/ b

### nesse ponto do script, as linhas 'um' e 'cinco' j no chegam mais.


### ento somente para as outras ser aplicado o prximo comando.

# coloque um '---' no comeo da linha

58
Dominando o SED - Arquivo

s/^/---/

# fim do bloco
}

### fim do script

Tudo bem, os comentrios esto exageradamente explicativos, mas a idia mostrar o quo
didtico pode ficar seu script sed. Com certeza ficou 78% mais fcil de ler! (No so irritantes
essas estatsticas subjetivas e absurdas que ouvimos diariamente?)

notvel a diferena do entendimento entre este script e a linha de comando anterior onde os
comandos estavam todos grudados. Moral da histria: fica a critrio do programador fazer um
cdigo pequeno e indecifrvel, ou extenso e legvel. Ambas as formas tm suas audincias.

Como os espaos em branco no comeo de cada linha so irrelevantes para o sed, temos a
liberdade de estruturar as linhas como preferirmos, podendo utilizar espaos e TABs. Note
tambm que como separamos os comandos um por linha, no precisamos mais colocar o
ponto-e-vrgula entre eles.

Cada um tem a liberdade de nomear os scripts sed como bem entender, no h um padro ou
norma. Mas para facilitar a identificao de seu contedo, aconselhvel utilizar a extenso .
sed. Este script de exemplo poderia se chamar seu-madruga-no-brasil.avi, mas bloco.sed
muito mais descritivo e apropriado, no concorda? &:)

59
Dominando o SED - Arquivo

Como utilizar um script sed


Agora que j sabemos como colocar os comandos sed num arquivo, tornando-os parte de um
script sed, resta saber como fazer o sed utilizar este script.

Basta usar a opo -f ou --file, seguida do nome do script, que serve para para dizer ao sed:
"Use os comandos que esto dentro deste arquivo". Veja:

prompt$ sed -f arquivo.sed texto.txt

Essa opo pode ser usada mais de uma vez na linha de comando, ento vrios scripts podem
ser usados no mesmo comando:

prompt$ sed -f arq1.sed -f arq2.sed -f arq3.sed texto.txt

O sed os interpreta seqencialmente, ou seja, a ordem de colocao dos vrios "-f" tem
importncia. Se o exemplo anterior fosse trocado para:

prompt$ sed -f arq3.sed -f arq2.sed -f arq1.sed texto.txt

o resultado no ser o mesmo.

60
Dominando o SED - Arquivo

Lembrando da escolinha: A ordem dos fatores ALTERA o produto

No acredita? Tudo bem, vamos demonstrao ento:

prompt$ cat abc.sed


s/abc/XXX/
prompt$ cat xxx.sed
s/XXX/xyz/
prompt$ echo abc | sed -f abc.sed
XXX
prompt$ echo abc | sed -f abc.sed -f xxx.sed
xyz
prompt$ echo abc | sed -f xxx.sed -f abc.sed
XXX

O script abc.sed troca "abc" por "XXX" e o xxx.sed pega esse "XXX" e troca por "xyz". Como o
xxx.sed depende da alterao feita pelo abc.sed, ele precisa ser executado depois, seno no
haver "XXX" para ele trocar.

Alm de vrios "-f", tambm possvel colocar comandos normais junto na mesma linha de
comando utilizando a opo -e, e fazer uma salada de frutas. As regras continuam as
mesmas: a "ordem de chegada" importante. Acompanhe:

prompt$ cat a.sed


s/a/X/g

61
Dominando o SED - Arquivo

prompt$ echo abc | sed -f a.sed


Xbc
prompt$ echo abc | sed -e 's/b/a/' -f a.sed
XXc
prompt$ echo abc | sed -e 's/b/a/' -f a.sed -e 's/c/X/'
XXX
prompt$ cat x.sed
s/X/./g
prompt$ echo abc | sed -e 's/c/a/' -f a.sed -e 's/b/X/' -f x.sed
...

Para no se perder na ordem, basta lembrar que o sed est recebendo vrios pedacinhos de
comandos, mas hora de executar, uma coisa s. como se ele fosse recebendo vrios
bilhetinhos de papel com tarefas fazer. Cada bilhete novo recebido colado com durex no
final do anterior, at que todos tenham sido entregues. Ao comear a execuo dos
comandos, o sed ter uma grande folha remendada e disforme de tarefas a fazer.

62
Dominando o SED - Arquivo

Como tornar executvel um script sed


No UNIX/Linux, scripts sed podem se tornar arquivos executveis, bastando digitar seu nome
para ser interpretado, sem precisar chamar com o sed -f. Essa mgica feita em dois passos:

1. Informar ao sistema que o arquivo executvel


2. Informar ao sistema como execut-lo

O primeiro passo um procedimento comum, aplicado a todos os arquivos do sistema que


devam ser executveis. necessrio alterar as caractersticas do arquivo, incluindo nele as
permisses de execuo. O comando chmod se encarrega disso e a opo a ser utilizada a
+x:

prompt$ chmod +x meu-script.sed

Quem utiliza o comando ls com cores, vai notar que script agora ficou verdinho. sinal que
ele j um arquivo executvel. Para garantir, ou no caso de um ls sem cores, use o comando
ls -l e veja se as permisses do arquivo ganharam alguns "x", mudando de "-rw-rw-r--" para
"-rwxrwxr-x". Veja:

prompt$ ls -l meu-script.sed
-rw-rw-r-- 1 mussum aa 284 Feb 2 17:10 meu-script.sed
prompt$ chmod +x meu-script.sed

63
Dominando o SED - Arquivo

prompt$ ls -l meu-script.sed
-rwxrwxr-x 1 mussum aa 284 Feb 2 17:10 meu-script.sed

Ok, temos um arquivo executvel. Mas ainda no informamos ao sistema que o sed quem
deve interpretar nosso script. Como fazer isso?

O shell, ao executar um arquivo, d uma olhadinha na primeira linha dele e v se os dois


primeiros caracteres so gradinha-exclamao #!. Se for, o restante dessa linha considerado
um comando de chamada, que diz ao shell como executar o arquivo. Funciona como um
manual de instrues para o shell ler &:)

Quem j tem alguma familiaridade com o shell e j fez ou viu algum script shell, certamente
conhece a primeira linha mgica que os torna especiais:

#!/bin/sh

Assim o shell sabe que precisa chamar o programa /bin/sh (que o prprio shell!) para
executar este arquivo. E isso funciona com qualquer outro comando do sistema. Ento para
um script sed, basta colocar como primeira linha o comando que normalmente usaramos
para interpret-lo:

#!/bin/sed -f

64
Dominando o SED - Arquivo

Note que preciso especificar o caminho completo do executvel do sed, pois o PATH no
levado em conta nesse momento. Pronto! O script agora um arquivo executvel legtimo.
Vamos test-lo?

prompt$ meu-script.sed texto.txt


bash: meu-script.sed: command not found

Opa! Como assim "comando no encontrado"? Ahhhh, que o diretrio corrente no est
includo no PATH do sistema, ento preciso colocar um ./ na frente do nome do script para o
shell encontr-lo:

prompt$ ./meu-script.sed texto.txt

Caso seu script fique muito bom (vai ficar, claro!) e voc o utilize com bastante freqncia,
copie-o para o diretrio dos programas de verdade para no precisar mais do ./ para cham-
lo:

prompt$ cp meu-script.sed /usr/bin

65
Dominando o SED - Arquivo

Como monitorar um arquivo com a ajuda do sed


No sed da GNU, a partir da verso 3.02.80, foi adicionada a opo -u (de "unbuered") que
instrui o sed a fazer um uso minimalista dos registradores ("buers"), tentando mostrar a
sada o mais rpido possvel.

No comportamento normal, o sed fica esperando at acabar todo o fluxo de texto (EOF), para
s ento comear a mandar para a sada o resultado do processamento. Com esta opo nova,
este tempo de espera no existe, e assim que ele acaba de processar uma linha, j a manda
para a sada instantaneamente.

A grande vantagem desse comportamento, no a velocidade de resposta, mas sim o fato de


no esperar o final do texto. Isso torna possvel editar um fluxo de texto interminvel. Pera,
como assim interminvel?

Sabe aqueles arquivos de registros ("log files"), que vo crescendo, crescendo


indefinidamente, com mensagens de erro, data, informaes e avisos? Alguns exemplos no
Linux so /var/log/messages e o /var/log/maillog. Enquanto o servio que gera estas
mensagens estiver ativo, ele continua escrevendo mais e mais texto em seu arquivo de log.

66
Dominando o SED - Arquivo

muito comum se precisar acompanhar em tempo real a apario das mensagens de log, para
diagnosticar problemas ou acompanhar eventos. Um utilitrio UNIX que faz isso o tail,
quando usado em conjunto com a opo -f. Ele monitora um arquivo, mostrando na tela cada
mensagem nova que aparece no fim do arquivo de registros.

Como geralmente um arquivo de registros mostra mensagens variadas, s vezes at com


excesso de informaes, torna-se necessrio o filtrarmos um pouco, e obter apenas as
mensagens relevantes nossa necessidade no momento. Opa, falou em filtro? Sed nele!

Um exemplo "da vida real" seria mostrar apenas as mensagens do sistema relativas s
conexes ssh:

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

E claro, ao invs de simplesmente mostrar a linha, o sed tambm j podia edit-la, tirar partes
que no interessam, colocar cdigos de cores para destacar informaes, etcetcetc. Mas no
vou tirar do leitor o prazer de fazer sozinho essas fresc^W melhorias.

Ah, e cuidado com esse -nu perto de crianas! &:)

67
Dominando o SED - Arquivo

Como ler o contedo de um arquivo


J sentiu a necessidade de no meio de um script sed, ler o contedo de um arquivo qualquer e
mand-lo para a sada? exatamente esta a funo do comando "r" (de "Read"). Mas ateno!
Como o sed gosta de fluxos de texto e no de arquivos, esse comando um pouco, como
dizer... equivocado.

A impresso que se tem que o sed estava pronto para sair do forno e de ltima hora chegou
o "Sr. Gerente Foobar" e mandou o programador colocar suporte a leitura de arquivos, em 5
minutos. O resultado que um comando que deveria ser simples (ler arquivos), cheio de
pegadinhas e falhas conceituais.

Ento quando usar este comando, tenha em mente que o contedo do arquivo enviado
sada...

... diretamente, no podendo ser editado


... somente no final do script, mesmo havendo comandos aps
... somente aps processada e impressa a linha atual do buer
... sempre, ignorando a opo -n (ou o #n na primeira linha)

68
Dominando o SED - Arquivo

Por esse resumo j deu para perceber os furos de implementao no ? Mas antes de ver os
detalhes, vamos aprender a us-lo, comeando com um exemplo bem comum: incluir
cabealho e rodap num arquivo qualquer.

Estamos fazendo algumas pginas de internet, e percebemos que os textos do incio (ttulo,
menu de navegao) e o do final (contato) so sempre os mesmos para todas as pginas.
Como somos espertos, guardamos estes textos padro em arquivos separados
(cabecalho.html e rodape.html), e usamos o sed para inclui-los automaticamente nas nossas
pginas HTML! Um exemplo genrico seria:

prompt$ sed -e '1 r cabecalho.html' -e '$ r rodape.html' meio.html > pagina.html

Incluindo o cabealho no incio (aps a linha 1) e o rodap no final (aps a ltima linha). O
comando UNIX similar seria:

prompt$ cat cabecalho.html meio.html rodape.html > pagina.html

O primeiro detalhe que percebemos no exemplo que precisamos separar os comandos


usando a opo -e. Mas por que isso? Bem, lembra do detalhe dos "5 minutos"? Pois . Na
definio de quais caracteres seriam vlidos para um nome de arquivo, o ponto-e-vrgula foi
includo. Pense um pouco sobre o efeito colateral disso...

69
Dominando o SED - Arquivo

Tudo bem, o ponto-e-vrgula um caractere que pode aparecer no nome de um arquivo. Mas
ele tambm o caractere que delimita onde termina um comando sed e comea outro! E voc
acha que h uma maneira especial de colocar o ponto-e-vrgula no nome do arquivo para que
o sed no confunda com o separador de comandos? Ha-ha. No.

Com essa implementao descuidada, o resultado no mnimo incmodo. Nos quatro


exemplos seguintes, o trecho em destaque o "nome do arquivo" que o comando "r" de cada
um tentar ler:

sed '1 r cabecalho.html ; $ r rodape.html' meio.html > pagina.html


sed 'r /tmp/arquivo.txt ; s/abc/XXX/ ; 5d' texto.txt
sed 'r c:\temp\arquivo.txt ; 10q' texto.txt
sed 'r arquivo.txt ; 1,/End:/!d' texto.txt

Entendeu a dificuldade? O ponto-e-vrgula que deveria separar os comandos, entendido


como parte do nome do arquivo, ento no h caractere que sirva para terminar esse nome.
Com isso, o sed considera o "nome do arquivo" tudo o que vier depois do "r", at o fim da
linha.

70
Dominando o SED - Arquivo

Para contornar essa dificuldade, o comando "r" (assim como o seu irmo, o comando "w") deve
estar isolado, no havendo nada aps ele seno o nome do arquivo desejado. Num script sed,
basta quebrar a linha aps o nome do arquivo. Na linha de comando deve-se usar o -e para
separar as partes do comando sed.

Entendido isso, vamos ao prximo "detalhe": o contedo do arquivo mandado diretamente


para a tela. O ideal seria o sed ler o arquivo e colocar o seu contedo no espao padro, para
podermos manipul-lo. Mas ao invs disso o contedo simplesmente "jogado" para a sada,
sem controle, sem edio.

Obs.: O ssed e o gsed-4 implementaram essa funcionalidade de ler o arquivo para o


espao padro com o comando "R" (maisculo)

Mas no acaba a. Alm de jogar o contedo na sada sem controle, o sed faz isso de maneira
no seqencial tambm! Olha o absurdo:

prompt$ cat abc.txt


#### Eu sou o contedo do arquivo
#### abc.txt, de duas linhas.

prompt$ echo | sed -e 's/.*/ANTES/p ; r abc.txt' -e 's/.*/DEPOIS/'


ANTES
DEPOIS
#### Eu sou o contedo do arquivo

71
Dominando o SED - Arquivo

#### abc.txt, de duas linhas.

O comando que foi usado possui trs partes:

1. Mostra a palavra "ANTES" na tela


2. Mostra o contedo do arquivo abc.txt
3. Mostra a palavra "DEPOIS" na tela

Esta deveria ser a ordem de execuo dos comandos, mas como observado, o sed s mostrou
o contedo do arquivo depois de completar o terceiro e ltimo comando! Mais uma pegadinha
do "efeito 5 minutos"...

Tem mais, tem mais! Caso tenha um comando "N" no script, que foraria a leitura da prxima
linha, o contedo do arquivo colocado no lugar certo:

prompt$ echo | sed -e 's/.*/ANTES/p ; r abc.txt' -e 's/.*/DEPOIS/ ; N'


ANTES
#### Eu sou o contedo do arquivo
#### abc.txt, de duas linhas.
DEPOIS

No tente entender, bug bug. E como esse um bug que vem desde os tempos mais
remotos do sed, dificilmente ser corrigido pois muitos scripts foram feitos baseados nessas
regras, e mud-las significa quebrar esses scripts.

72
Dominando o SED - Arquivo

Para finalizar a sesso de detalhes do comando "r", ele passa por cima da opo -n. Essa
opo deixa a sada do sed silenciosa, apenas mostrando texto quando especificado pelos
comandos "P p l". Na prtica vemos que o comando "r" imune a essa opo e mostra o
contedo do arquivo sempre.

prompt$ echo | sed -n 'r abc.txt'


#### Eu sou o contedo do arquivo
#### abc.txt, de duas linhas.

73
Dominando o SED - Arquivo

Como gravar um trecho de texto num arquivo


Assim como temos o comando "r" para a leitura de arquivos, tambm temos o comando
complementar "w", que grava num arquivo o contedo atual do espao padro.

Lembra do "Sr. Gerente Foobar" do tpico anterior? Pois , alm do comando de leitura, ele
tambm mandou o pobre programador fazer um comando de gravao de texto em arquivos.
Mas como dessa vez ele foi mais generoso e deu o prazo de 10 minutos, este comando ficou
um pouco melhor que o anterior. Detalhes:

A linha gravada imediatamente, no espera o fim do script como o "r"


O arquivo sempre truncado, e seu contedo anterior perdido
O arquivo sempre truncado mesmo que o comando "w" no seja executado
O nome do arquivo aceita ponto-e-vrgula, ento o comando deve estar separado dos
demais (-e)

Mas antes dos detalhes, vamos ao uso. Por exemplo, se voc quer gravar num arquivo o
resultado de uma busca por linhas que contm a palavra "estorvo". O comando UNIX seria:

prompt$ grep 'estorvo' texto.txt > estorvos.txt

E o similar em sed:

74
Dominando o SED - Arquivo

prompt$ sed -n '/estorvo/w estorvos.txt' texto.txt

Traduzindo: Para cada linha do arquivo texto.txt que encontrar a palavra estorvo, grave-a no
arquivo estorvos.txt.

Como irmo do comando "r", o "w" sofre do mesmo problema da especificao do nome do
arquivo e o ponto-e-vrgula. Isso quer dizer que se deve usar a opo -e para separar os
comandos, ou quebrar a linha quando utiliz-lo. Como no exemplo anterior o "w" era o nico
comando, a separao no foi necessria.

Uma outra utilidade de se gravar dados num arquivo a de servir como um espao auxiliar
caso voc j esteja usando o RESERVA e ainda precisa de outro cantinho para guardar dados
durante a execuo do script. Um exemplo clssico, se processar um documento
estruturado, com ttulos e sees, e no final imprimir uma lista de tpicos (TOC), apenas com
os ttulos:

prompt$ sed -e '/<H1>/ w /tmp/toc' -e '$ r /tmp/toc' documento.html

Neste exemplo simples, gravamos num arquivo temporrio todos os ttulos de um documento
HTML, que so identificados pela marca "<H1>". Somente quando estivermos na ltima linha
do arquivo ($), lemos o contedo do arquivo temporrio, que contm todos os ttulos
agrupados.

75
Dominando o SED - Arquivo

Apenas como curiosidade, o comando similar que utiliza o RESERVA e a tcnica j


demonstrada de "como fazer um lao utilizando o reserva":

prompt$ sed '/<H1>/ H ; $! d ; g' documento.html

Vejamos agora uma caracterstica, ou limitao dependendo do caso. Se o arquivo a ser


gravado no existir, o sed o criar. Porm caso ele j exista, o sed primeiro o truncar para
depois utiliz-lo.

J vimos que truncar significa perder todo o contedo anterior. Ento este arquivo no pode
ser usado como arquivo de registros ("logfile") ou como algum tipo de histrico, pois ele
"varrido" a cada execuo do script.

E uma caracterstica da caracterstica, que alm de truncar o arquivo, no que o danado faz
isso imediatamente, assim que chamado?! E ele faz isso mesmo que o comando "w" nem
venha a ser executado. Ou seja, se tiver algum "w" no script, primeiro o sed vai l e trunca o
arquivo, s depois o script executado. A j no importa mais se o trecho do comando "w"
vai ser necessrio ou no, pois o contedo do arquivo j foi apagado mesmo...

Usando o "w", o arquivo SEMPRE truncado

76
Dominando o SED - Arquivo

Esse comportamento facilmente verificvel com este comando:

prompt$ sed '1 q ; 2 w /tmp/arquivo' arquivo.txt

Como o primeiro comando diz que na linha 1 o script deve ser abortado (comando "q"), o
resto dele (comando "w") nunca chegar a ser executado. Mesmo assim, o arquivo /
tmp/arquivo ser zerado.

Esse comportamento impede que se utilize o mesmo arquivo para um comando r seguido de
um comando w, ou seja, mostrar seu contedo atual antes de grav-lo. Muito cuidado!

77
Dominando o SED - Quebra de linha

Quebra de linha
Lidar com quebras de linhas com certeza umas das tarefas mais chatas de se fazer com o
sed, chatas no sentido de se tomar cuidado e saber de algumas "pegadinhas".

Mmmmmm, ser que eu devo contar os segredos e desmistificar todo o assunto para voc? ...
Claro!

Para comear, a quebra de linha no pode ser casada, alis, pode. Ou melhor: depende.

Ento primeiro vamos entender o que exatamente uma quebra de linha. Temos o cifro $
que indica o fim da linha, que o que vem antes da quebra da linha. Lembre-se da mquina
de escrever, ao chegar ao final da linha voc puxa o bracinho e o carretel gira, esta seria a
quebra de linha, que no Linux j vem de brinde com o retorno do carretel. Trrrrrrr tshhhhhh
plin!

Ento se voc tem um arquivo como este:

- uma serra pequena


- um alicate de bico com cabo
de borracha
- uma chave de fenda

78
Dominando o SED - Quebra de linha

E quer juntar a linha do alicate que se quebrou, o que fazer? A tentativa bvia seria /alicate/
s/\n// para apagar o \n, mas isso no funciona. E lembrando que a primeira parte do comando
s nada mais do que uma busca, ento similarmente o endereo /cabo\nde borracha/ no vai
funcionar como esperado.

79
Dominando o SED - Quebra de linha

Como apagar uma quebra de linha, juntando duas


linhas
Temos um problema: no podemos casar a quebra de linha, ento como apag-la?

Precisaremos usar de engenhosidade aqui. Lembra do comando N? Ele gruda a prxima linha
no padro, separando-a da linha atual por um \n. Ento aps aplicado o comando N, temos
duas linhas juntas numa string s, e surpresa: esse \n pode ser usado na busca!

Ento para nosso exemplo acima, quando estivermos na linha do alicate, grudaremos a
prxima linha, apagaremos o \n e pronto! A quebra de linha foi embora. Acompanhe:

prompt$ sed '/alicate/ N ; s/\n//' arquivo


- uma serra pequena
- um alicate de bico com cabode borracha
- uma chave de fenda

pa! Quase isso. Simplesmente apagar o \n vai grudar as duas palavras, ento o trocaremos
por um espao ao invs disso.

prompt$ sed '/alicate/ N ; s/\n/ /' arquivo


- uma serra pequena
- um alicate de bico com cabo de borracha

80
Dominando o SED - Quebra de linha

- uma chave de fenda

Aaaaaaaaah, agora sim. Vamos ver o debug para visualizar esse \n?

10 PATT:- um alicate de bico com cabo$


11 HOLD:$
12 COMM:/alicate/ N
13 PATT:- um alicate de bico com cabo\nde borracha$
14 HOLD:$
15 COMM:s/\n/ /
16 PATT:- um alicate de bico com cabo de borracha$
17 HOLD:$

Como podemos ver l est a linha do alicate no padro (L10). Depois de aplicado o N (L12), l
veio a prxima linha, e ficou o \n enfiado no meio das duas (L13). Da ficou fcil, chegou o s
(L15) e trocou o separador pelo espao em branco (L16).

81
Dominando o SED - Quebra de linha

Como apagar todas as quebras de linha, deixando


tudo numa s linha
Mas o do alicate foi para apenas uma linha. E se precisssemos fazer isso no arquivo todo,
juntando todas as linhas numa s? Vamos usar agora o arquivo de nmeros para ver melhor.

Para facilitar o trabalho dos descrentes, o jeito no-sed seria com o tr:

tr -d '\012' < numeros.txt

Pensando logicamente, se antes aplicamos o N endereado linha do alicate, agora basta no


colocar o endereo e ele ser aplicado para todas as linhas!

prompt$ sed 'N ; s/\n/ /' numeros.txt


um dois
trs quatro
cinco seis

Ei, o sed est maluco, ele pegou de dois em dois! Vamos ver o que aconteceu:

1 PATT:um$
2 HOLD:$
3 COMM:N
4 PATT:um\ndois$

82
Dominando o SED - Quebra de linha

5 HOLD:$
6 COMM:s/\n/ /
7 PATT:um dois$
8 HOLD:$
9 um dois
10 PATT:trs$
11 HOLD:$
12 COMM:N
13 PATT:trs\nquatro$

Ele grudou a segunda linha (L4), apagou a quebra (L6) mas depois comeou de novo na
terceira linha (L10). claro! Sabemos que ao chegar ao final do script, o sed l a prxima linha
e volta para o comeo do script.

83
Dominando o SED - Quebra de linha

Como fazer um lao


O que precisamos aqui fazer um lao (loop), impedir que o sed chegue ao final do script, e
ao invs disso, voltar ao comeo e sempre reexecutar o N.

Para isso, fazemos uma marca no comeo do script, chamaremos de "inicio", e sempre
voltaremos para ela em todas as linhas. Traduzindo isso para sed, fica:

:inicio ; N ; s/\n/ / ; b inicio

No sed da GNU esse script dar certo, mas em alguns seds ele sair com erro pois o N foi
aplicado na ltima linha (ver captulo do N). Ento colocaremos um condicional aqui, para no
aplicar o N na ltima linha: $!N, ou falando a lngua do sed: aplique o N para todas as linhas,
exceto a ltima.

:inicio ; $! N ; s/\n/ / ; b inicio

Mmmmmmm, para os j iniciados em programao, notaram que o que acabamos de fazer foi
um lao infinito? Se dissemos ao sed para sempre voltar ao comeo do script, ele far isso
infinitamente, consumindo toda a CPU de seu computador. Legal n? &:)

84
Dominando o SED - Quebra de linha

Como fazer um lao com condicional de sada


O que precisamos aqui colocar um condicional que diga: se acontecer tal coisa, saia do lao.
O que seria essa "tal coisa"? Como queremos grudar o arquivo todo numa linha s, devemos
aplicar o N at a ltima linha. pa! Achamos nosso condicional: se estiver na ltima linha, saia
do lao.

Vamos ver como fazer esse condicional. Sabemos como representar a ltima linha ($), mas
como sair do lao? Vamos analisar nosso script:

:inicio ; $! N ; s/\n/ / ; b inicio


^ |
\_________________________/

Esse o lao, precisamos de uma rota alternativa para o fim do script:

_______________________________________
/ \
| v
:inicio ; $<alguma-coisa> ; $! N ; s/\n/ / ; b inicio <destino>
^ |
\__________________________________________/

85
Dominando o SED - Quebra de linha

Ei, se formos ver direto, essa sada do lao a mesma tcnica que foi usada no prprio lao!
Basta fazermos uma marca no fim e pularmos at ela:

__________________________________
/ \
| v
:inicio ; $ b fim ; $! N ; s/\n/ / ; b inicio ; :fim
^ |
\__________________________________/

Ento estamos no lao, sempre voltando ao comeo, mas quando chegarmos na ltima linha,
pulamos para o fim. Ei ei ei! Notaram que na ltima linha pularemos direto para o fim e o N
nem ser executado? Sendo assim, ele no precisa mais daquele condicional que tnhamos
colocado antes:

prompt$ sed ':inicio ; $ b fim ; N ; s/\n/ / ; b inicio ; :fim' numeros.txt


um dois trs quatro cinco seis

YOU WIN. PERFECT!

86
Dominando o SED - Quebra de linha

Como fazer um lao com condicional de entrada


Um outro tipo de condicional que podemos fazer o contrrio, colocando um condicional que
faa o script voltar ao comeo: se tal coisa, volte. Assim o lao fica condicionado, e s ocorre
se a condio for satisfeita.

Alm do comando b, tambm podemos dar pulos com o comando t, que s executa o pulo se
o ltimo comando s fez uma substituio. pa! Aqui est a palavra mgica "se". Ento o
prprio t j um comando com condicional.

Ento basicamente usamos o mesmo exemplo anterior com a marca :inicio e trocamos o b
pelo t:

:inicio ; N ; s/\n/ / ; t inicio

Mas lembrando do problema do N na ltima linha, precisamos colocar de volta aquele outro
condicional esperto:

prompt$ sed ':inicio ; $! N ; s/\n/ / ; t inicio' numeros.txt


um dois trs quatro cinco seis

87
Dominando o SED - Quebra de linha

Ento em todas as linhas o N grudar a prxima, com o \n de separador e o s o trocar por um


espao. Como a substituio foi feita, o t pular de volta ao incio e o ciclo se fecha at a
ltima linha.

Na ltima linha, o condicional $!N impede que o N seja executado, logo no haver \n, ento o
s no vai ter o que substituir e assim o t no pular de volta ao comeo, finalizando o script.

FINISH HIM! FATALITY!

88
Dominando o SED - Quebra de linha

Como fazer um lao utilizando o reserva


Uma outra maneira de fazer um lao, utilizar o espao reserva e ir "estocando" l as linhas
que se deseja, e ao encontrar o ponto de parada, carregar o estoque para o padro e trabalh-
lo.

Ainda na nossa rdua tarefa de juntar todas as linhas numa s, vamos ver como fica nosso
script utilizando esta tcnica:

prompt$ sed 'H ; $! d ; g ; s/\n/ /g' numeros.txt


um dois trs quatro cinco seis

Ganhamos um espao em branco no comeo da linha que pode ser facilmente apagado com
um s/.// no final do script. Mas fora isso, como funciona o lao?

1 PATT:um$
2 HOLD:$
3 COMM:H
4 PATT:um$
5 HOLD:\num$
6 COMM:$ !d
7 PATT:dois$
8 HOLD:\num$
9 COMM:H
10 PATT:dois$
11 HOLD:\num\ndois$

89
Dominando o SED - Quebra de linha

O H (L3) juntou o contedo do padro ("um") no reserva, separando-o do contedo j existente


por um \n (L5). Como a primeira linha e o reserva estava vazio, no tem nada antes do \n. O
prximo comando d est condicionado a no ser executado na ltima linha, ou seja, ele ser
aplicado para todas as outras. Como ainda estamos na primeira linha, ela foi apagada, e como
o d aps apagar j carrega a prxima linha no padro e faz o script sed voltar ao comeo,
novamente o H vai ser executado (L9), fechando o ciclo. E assim o padro vai sendo juntado no
reserva (L11), linha aps linha at a ltima, s executando os primeiros comandos H; $!d:

31 PATT:seis$
32 HOLD:\num\ndois\ntrs\nquatro\ncinco$
33 COMM:H
34 PATT:seis$
35 HOLD:\num\ndois\ntrs\nquatro\ncinco\nseis$
36 COMM:$ !d
37 PATT:seis$
38 HOLD:\num\ndois\ntrs\nquatro\ncinco\nseis$
39 COMM:g
40 PATT:\num\ndois\ntrs\nquatro\ncinco\nseis$
41 HOLD:\num\ndois\ntrs\nquatro\ncinco\nseis$
42 COMM:s/\n/ /g
43 PATT: um dois trs quatro cinco seis$
44 HOLD:\num\ndois\ntrs\nquatro\ncinco\nseis$
45 um dois trs quatro cinco seis

90
Dominando o SED - Quebra de linha

Ao chegar na ltima linha, ela tambm ser juntada no reserva, mas agora o condicional $!d
faz com que o d no seja aplicado, ento o script pode continuar finalmente para o prximo
comando g (L39). Com ele, recuperamos todo o contedo do nosso estoque de linhas, e o
prximo comando s se encarrega de trocar todos (note o modificador s///g) os \n do padro
por espaos de uma s vez (L43).

Resumindo: estocamos as linhas no reserva, pegamos de volta e formatamos.

91
Dominando o SED - Quebra de linha

Como substituir alguma coisa por uma quebra de


linha
Uma tarefa comum voc ter um arquivo com vrios dados separados por algum delimitador
qualquer e querer que cada um dos dados fique em uma linha, ou seja, trocar o delimitador
por uma quebra de linha.

Mas com outras verses do sed que no entendem este escape, a quebra de linha deve ser
inserida literalmente e deve ser escapada:

prompt$ sed 's/ /\

prompt$ /g' texto.txt

No sed da GNU, a partir da verso 3.02.80(*), foi adicionado o \n como escape vlido dos dois
lados do comando s///. Com isso a tarefa de colocar cada palavra numa linha isolada, ou seja,
trocar espaos em branco por quebras de linha, fica trivial:

prompt$ sed 's/ /\n/g' texto.txt

92
Dominando o SED - MAISCULAS/minsculas

MAISCULAS/minsculas
A princpio parece ser um assunto to bobinho, que no tem muito o que falar, mas a
experincia mostra que o assunto maisculas/minsculas sempre vai render problemas e
solues diversos. Vamos fazer um apanhado de todos os tpicos que envolvem o assunto, e
no deixar nem uma sombra de dvida no caminho.

Vamos comear com a notao, que pode ser novidade para muitos. Como vamos falar de
tipos de caracteres e converses entre eles, a linguagem tipogrfica serve para definirmos os
termos que identificam as aes e elementos do maravilhoso mundo das letras. Ento vamos
l: letras em maisculas so letras com caixa alta, e em minsculas, caixa baixa. Ento
inverter a caixa o nome que se d troca de maisculas por minsculas e vice-versa.
Destes termos tambm podemos derivar: levantar a caixa, que seria a "maiusculizao"
(toupper) e abaixar a caixa seria a "minusculizao" (tolower).

93
Dominando o SED - MAISCULAS/minsculas

Como deixar todo o texto em caixa alta (ou baixa)


Uma tarefa das mais bsicas e corriqueiras quando se manipula textos precisar padronizar a
caixa das letras, convertendo todas as palavras para caixa alta, ou baixa.

A ferramenta UNIX que faz isso o tr, que possui o clssico tr [A-Z] [a-z] para abaixar a
caixa de um texto. Ah! Em verses mais recentes os colchetes no so mais necessrios ento
tr A-Z a-z basta. O sed possui tambm um comando de traduo de caracteres, o y. Essa
traduo feita caractere a caractere, por exemplo:

sed 'y//aeo/' arquivo.txt

Este comando trocar as letras com acento agudo pela prpria letra sem acento. Diferente do
comando s///, que "troque isso por aquilo", o y/// "para cada letra daqui, troque-a pela de
l". Ento no comando anterior, estamos dizendo ao sed: "troque por a, troque por e,
troque por o".

Outra diferena do s, em que se tem controle sobre o nmero de substituies que sero
feitas, com o y tudo ou nada, ele converte todas as letras da linha que estiverem no
comando. Veja:

prompt$ echo AAAABBBAAAA | sed 'y/AB/ab/'


aaaabbbaaaa

94
Dominando o SED - MAISCULAS/minsculas

E o y sempre assim, em pares. Por isso sempre deve haver o mesmo nmero de letras na
primeira e na segunda parte do comando, seno o sed acusar erro.

Outro detalhe que o y por causa dessa paridade, s aceita caracteres literais. Nada de
expresses regulares ou qualquer outro caractere especial. Ento o comando similar ao tr
invlido:

sed 'y/A-Z/a-z/' # ERRADO!

Este comando diz: "troque A por a, troque - por -, troque Z por z", e s. Para conseguirmos
converter de maisculas para minsculas, temos que colocar todas as letras, uma por uma.
Sim, isso muito chato.

sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'

Essa minhocona far o servio de deixar todo o texto em caixa baixa. Ser que voc est bem
atento? Apesar de j estar um comando gigantesco, no est faltando nada a no? claro!
Esto faltando nossas queridas letras acentuadas. Se no as colocarmos, continuaro em caixa
alta mesmo aps a converso. Respire fundo, vamos l:

sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'

95
Dominando o SED - MAISCULAS/minsculas

Ufa! Quanta coisa para resolver algo aparentemente to simples. Caso tenhamos nos perdido
no meio do caminho, e olha que isso muito fcil de acontecer, o sed avisar:

sed 'y/FGHI/fg/'
sed: -e expression #1, char 10: strings for y command are different lengths

Para fazer o caminho inverso, deixando tudo em maisculas, basta inverter as partes do
comando:

sed 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'

Uma dica muito, mas muito boa para a utilizao do y, usar outro delimitador. Assim como
para endereos e para o comando s, podemos usar qualquer caractere ASCII como delimitador
do comando. Ento ao invs da barra /, use a quebra de linha como delimitador:

sed 'y
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
'

Assim facilita muito, j ficando visualmente notvel caso as duas partes do comando tenham
tamanhos diferentes, e tambm visualizamos na hora quais so os pares de caracteres, pois
esto um embaixo do outro.

96
Dominando o SED - MAISCULAS/minsculas

Claro que para digitar na linha de comando, ficar quebrando linhas assim incmodo, mas
dentro de um arquivo, a melhor opo para no confundir.

97
Dominando o SED - MAISCULAS/minsculas

Como inverter a caixa de todas as letras


Agora que j sabemos como usar o comando y para aumentar ou abaixar a caixa das letras, e
sabendo que ele funciona em pares de letras, fica fcil inverter a caixa de todas as letras da
linha.

Primeiro faamos um teste rpido para ver se ele no converte duas vezes a mesma letra:

prompt$ echo aaaAAA | sed 'y/aA/Aa/'


AAAaaa

Beleza! Ento para fazer o superconversor basta pacientemente compor a superminhoca num
superscript!

# inverte_caixa.sed (dica: usa quebra de linha como separador)


y
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz

Admita: o sed lindo no ? Temos um script de apenas 3 linhas, sem nenhum smbolo,
apenas letras. E isso inverte a caixa de todas as letras. Vamos testar?

prompt$ echo "SED significa Stream EDitor" | sed -f inverte_caixa.sed


sed SIGNIFICA sTREAM edITOR

98
Dominando o SED - MAISCULAS/minsculas

Como levantar a caixa da primeira letra de cada linha


Antes de mais nada, no pense que vai ser fcil. D uma looonga respirada, vista o capacete
anti-maionese, e vamos viajar!

Lembra que o comando y troca sempre todas as letras da linha? Ento como fazer para que
ele troque apenas a primeira letra e mantenha as outras intactas? Mmmmmmmmm,
precisamos de um pouco de mgica aqui.

Temos dois componentes: a linha e o comando. Como no tem jeito de mudar o y, que
sempre pega a linha toda, s nos resta ento mudar a prpria linha. A soluo isolar apenas
a primeria letra no PADRO, deixando-a sozinha para que o y faa o seu servio, e depois
rejuntar o resto da linha novamente. , muito feio, mas o que d pra fazer.

Primeiro problema: isolar a primeira letra. Antes de mais nada, guardamos uma cpia da linha
original no RESERVA (comando h). Em seguida, apagamos todo o resto da linha, deixando
apenas a primeira letra. Geralmente a primeira letra da frase j est bem no comeo da linha,
ento a expresso regular ^[a-z] serve para represent-la. Mais adiante vamos refinar esta
expresso, mas por enquanto deixemos assim. Ento se j sabemos como identificar a
primeira letra, apagamos tudo menos ela:

h ; s/^\([a-z]\).*/\1/

99
Dominando o SED - MAISCULAS/minsculas

Supondo a frase "unidos venceremos!", aps aplicado o comando acima teremos:

PATT: u$
HOLD: unidos venceremos!$

Com a primeira letra isolada, agora podemos levantar sua caixa tranquilamente com a famosa
minhocona y/abcde.../ABCDE.../.

Beleza, ento agora temos que voltar o resto da linha que est no RESERVA, mas antes temos
que tambm retirar a primeira letra dela, pois ela uma cpia da linha original lembra?
Devemos trocar os registradores de lugar e apagar a letra:

x ; s/^[a-z]//

Agora temos em mos:

PATT: nidos venceremos!$


HOLD: U$

Certo, agora basta grudar o PADRO no RESERVA (comando H), e apagar o \n que vai ficar
entre eles:

H ; g ; s/\n//

100
Dominando o SED - MAISCULAS/minsculas

Compondo o script todo fica:

h ; s/^\([a-z]\).*/\1/ ;# guarda cpia, deixa s a primeira letra


y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/ ;# levanta a caixa
x ; s/^[a-z]// ;# arranca a primeira letra da cpia
H ; g ; s/\n// ;# remonta a linha

Sem querer ser chato mas sendo, esse script ainda no 100% funcional. At aqui assumimos
que geralmente a primeira letra da frase j est bem no comeo da linha. Mas como isso nem
sempre verdade, temos que melhorar nossa expresso regular ^[a-z].

Antes da primeira letra, podemos ter espaos em branco, ento prudente tambm colocar
esta condio na expresso: ^ *[a-z]. , mas alm de espaos, tambm podem ter TABs, ento
melhor garantir e fazer ^[[:blank:]]*[a-z]. E o monstro vai crescendo...

Sendo mais chato ainda: e os acentos? Temos palavras no portugus que comeam com
acentos? Deixa ver: gua, poca, dio, cio, rbita... cus, tambm precisamos incluir os
acentos para que nosso script no falhe. Vamos l: ^[[:blank:]]*[[:lower:]]. Agora chega!
Esse monstrinho representa a primeira letra de uma linha.

Vamos atualizar nosso script com essa informao nova. Ah! Lembre que o y/// agora tambm
precisar conter os caracteres acentuados!

# _L_inha.sed

101
Dominando o SED - MAISCULAS/minsculas

h ; s/^\([[:blank:]]*[[:lower:]]\).*/\1/ ;# guarda cpia, deixa s a primeira letra


y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
x ; s/^[[:blank:]]*[[:lower:]]// ;# arranca a primeira letra da cpia
H ; g ; s/\n// ;# remonta a linha

Que trabalheira para fazer uma coisa to simples hein? Pois , essa a eterna diverso de se
usar o sed &:D Apenas como comparativo, para fazer a mesma coisa no vim basta um s/
[[:lower:]]/\u&/.

102
Dominando o SED - MAISCULAS/minsculas

Como levantar a caixa da primeira letra de cada


palavra
Se o tpico anterior de levantar a caixa s da primeira letra da linha j era complicado,
imagina este: cabeludo. To cabeludo que precisaremos de trs seds.

O primeiro sed quebra a linha em cada palavra, deixando uma por linha
O segundo sed o _L_inha.sed do tpico anterior, j que temos uma palavra por linha
O terceiro sed reajuntar as palavras numa linha.

O grande conselho : use outro programa. Mas se o sed a nica opo, ou se S&M significa
algo para voc, vamos l!

Para quebrar a linha em cada palavra, temos um carinha muito til que o \<, que representa
um "incio de palavra", ento basicamente trocamos um "incio de palavra" por uma "quebra de
linha". Na lngua do sed, isso :

# uma-palavra-por-linha.sed

s/\</\
/g

103
Dominando o SED - MAISCULAS/minsculas

Como o segundo sed j temos, j podemos testar os dois primeiros passos!

prompt$ echo "eu nunca farei isso." | sed -f uma-palavra-por-linha.sed | sed -f _L_inha.sed
Eu
Nunca
Farei
Isso.

E claro, para juntar todas as linhas, h vrias opes descritas no tpico "Como apagar todas
as quebras de linha, deixando tudo numa s linha". Colocando uma verso compacta do lao
com condicional de entrada, temos:

# junta-linhas.sed

:i ; $!N ; s/\n/ / ; ti

O comando completo fica algo deselegante, mas funciona:

prompt$ echo "eu nunca farei isso." | sed -f uma-palavra-por-linha.sed | sed -f _L_inha.sed
| sed -f junta-linhas.sed
Eu Nunca Farei Isso.

Se possvel, bom colocar todos estes comandos dentro de um script shell, e ento voc ter
quatro arquivos para fazer uma tarefa simples!

#!/bin/sh

104
Dominando o SED - MAISCULAS/minsculas

# _P_alavra.sh - levanta a caixa da primeira letra de cada palavra

sed -f uma-palavra-por-linha.sed |
sed -f _L_inha.sed |
sed -f junta-linhas.sed

Mas pelo menos a linha de comando fica menor:

prompt$ echo "eu nunca farei isso." | ./_P_alavra.sh

E j que chegamos at aqui, podemos ter apenas um arquivo, colocando o contedo dos trs
seds direto dentro do script shell:

#!/bin/sh
# _P_alavra.sh - levanta a caixa da primeira letra de cada palavra

sed 's/\</\
/g' |

sed '
h ; s/^\([[:blank:]]*[[:lower:]]\).*/\1/
y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
x ; s/^[[:blank:]]*[[:lower:]]//
H ; g ; s/\n//' |

sed ':i ; $!N ; s/\n/ / ; ti'

Novamente, o comando equivalente no vim seria mais simples: s/\<./\u&/g

105
Dominando o SED - MAISCULAS/minsculas

Como ignorar a diferena de maisculas e minsculas


normal ao se pesquisar dados, querer ignorar a caixa do texto procurado, ou seja, tanto faz
se o texto estiver em maisculas ou minsculas, ambos so vlidos.

A grande maioria dos editores de texto, leitores de email, navegadores e outros programas
que manipulam texto tm a opo de ignorar a caixa quando pesquisando por um texto. No
vim :set ic, no grep atravs da opo -i e no sed: depende.

Mais uma vez entramos num tpico onde a verso do sed influi muito nas caractersticas e
poderes disponveis, ento se prepare para a chuva de possibilidades para algo aparentemente
to inocente.

Suponhamos a tarefa de apagar o telefone do amigo Pedro, que es...

A maneira mais tradicional, conservadora e garantida, que com certeza funcionar em todas
as verses de sed existentes, especificar uma a uma as possibilidades de cada letra do
padro, utilizando expresses regulares. Veja:

prompt$ sed '/[..][..][..]/d' bla.txt

106
Dominando o SED - MAISCULAS/minsculas

Usando os colchetes, explicitamos as alternativas possveis para cada posio de caractere do


padro.

Esta claro, no uma soluo prtica, pois sempre precisamos saber de antemo qual o
padro a ser procurado para colocar as alternativas. Mas se este padro mutvel, ou pode
ser definido pelo usurio, preciso pr-process-lo, colocando automaticamente os colchetes
e todas as alternativas, antes de pass-lo ao sed. Algo como:

- coloque o padro todo em minsculas


- para cada letra do padro, componha:
[
+ a prpria letra
+ a letra em caixa alta
+ ]

J imaginou todo esse trabalho s para pesquisar um texto? Infelizmente para uma grande
parte das verses de sed existentes, isso ou...

Se a sada puder ser toda em minsculas ou maisculas, outra ttica antes de mais nada
usar o comando y para converter a linha toda do arquivo de texto todo para maisculas, e
usar o padro tambm em maisculas. Essa ttica muito usada em programao, para
comparar contedo de variveis, por exemplo:

if ( toupper($comando) == 'SELECT' ) ; then ...

107
Dominando o SED - MAISCULAS/minsculas

Em sed, seria:

# aps ler a linha do arquivo texto, levante sua caixa


y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/

# procure o padro e execute os comandos


/MEU-PADRAO/ {
...
}

Mas para alvio dos amantes do sed, os programadores da GNU incluram um modificador
especial de endereo I (de Ignore-case) a partir da verso 3.01-beta1. A sintaxe pode parecer
estranha, mas acostuma. No endereo, basta colar o modificador I logo aps fechada a
segunda barra delimitadora:

prompt$ sed '/root/I d' texto.txt

E tambm no comando s///, temos o mesmo modificador I, que pode ser includo no final,
junto com os outros modificadores j existentes g, p, w, ou nmeros. Dessa maneira a primeira
parte do comando, que nada mais seno um endereo, pesquisada ignorando a caixa das
letras. Exemplo:

prompt$ sed 's/root/administrador/Ig' texto.txt

108
Dominando o SED - Cumbuca

Cumbuca
Aqui aquela seo que voc vai ler agora apressadamente, e depois quando precisar, vai
voltar para procurar um exemplo.

109
Dominando o SED - Cumbuca

Exemplos teis
"Olha, no que eu seja preguioso, eu j aprendi bastante coisa de sed, j me viro sozinho,
manjo de fazer endereos, de fazer scripts sed e tudo mais. Mas ser que no dava pra
colocar num cantinho a uns exemplinhos mastigados daquelas tarefas bem rotineiras e
chatas?"

Apagar todas as tags HTML s/<[^>]*>//g

Obter o nmero da linha onde est a palava VERDE /VERDE/= ; d

Remover todas as linhas em branco /^ *$/d

Remover todos os comentrios /^ *#/d

Comentar a linha que contm a palavra VERDE /VERDE/s/^/#/


y//
Desacentuar um arquivo AAAAEEIOOUUCaaaaeeioouuc/

Juntar todas as linhas numa s H ; $!d ; g ; s/\n/ /g

Remover todos os colchetes s/[][]//

Remover todos os colchetes e seu contedo s/\[[^]]*]//

Tirar caracteres de controle como ^[33;43m (^[ Ctrl+v,ESC) s/^[\[[0-9;]*m//

110
Dominando o SED - Cumbuca

Emulando comandos UNIX/Linux


A utilidade do sed s vezes supera os limites do palpvel. Se imagine numa mquina que s
tenha a instalao padro do Windows. um golpe duro, um pesadelo, ser privado de todas as
suas ferramentas UNIX/Linux que voc est acostumado a utilizar no dia-a-dia, como
trabalhar com os braos amarrados.

Mas espere, nem tudo est perdido! Se voc conseguir colocar nessa mquina pelo menos o
sed, poder us-lo para emular alguns dos seus comandos queridos. Emular significa imitar,
simular, ter comportamento idntico.

Ento instale o SED.EXE (DOS) e corra para o abrao!

comando | emulao
-------------+----------------------------------------
cat | sed :
tac | sed 1!G;h;$!d
grep | sed /padro/!d
grep -v | sed /padro/d
head | sed 10q
head -1 | sed q
tail | sed -e :a -e $q;N;11,$D;ba
tail -1 | sed $!d
cut -c 10 | sed s/\(.\)\{10\}.*/\1/
cut -d: -f4 | sed s/\(\([^:]*\):\)\{4\}.*/\2/
tr A-Z a-z | sed y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/

111
Dominando o SED - Cumbuca

tr a-z A-Z | sed y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/


tr -s ' ' | sed s/ \+/ /g
tr -d '\012' | sed H;$!d;g;s/\n//g
wc -l | sed -n $=
uniq | sed x;G;/^\(.*\)\n\1$/d;g
rev | sed /\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//
basename | sed s,.*/,,
dirname | sed s,[^/]*$,,
cp | sed w arquivo-novo

112
Dominando o SED - Agradecimentos

Agradecimentos
Em Outubro de 2002, alguns amigos toparam ajudar com o livro. Eu lhes mostrei o texto e
eles sugeriram melhorias, arrumaram erros ortogrficos e fizemos uma grande discusso que
resultou no aumento de qualidade do contedo. A esse grande time meu MUITO OBRIGADO:

Eliphas Levy Theodoro


rico "DyNaMiTe"
Fernando Braga
Gentil de Bortoli Jnior
Julio Cezar Neves
Leslie Harlley Watter
Luciano Esprito Santo
Marcelo Pereira
Rodrigo Stulzer
Rubens Queiroz de Almeida
Thobias Salazar Trevisan

113

Você também pode gostar