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 car 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 ocial 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 compillo.

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, nd, vi e dezenas de outros programas. Vale conferir!

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.

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, especicar 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. Anal, 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 redenir 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 conar em posies xas porque elas raramente so xas de verdade. Elas se mudam sem deixar telefone, email... &:) Tendo em vista estas necessidades, tambm podemos denir 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 especicar 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 deni-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 ca 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 especicar dois endereos, um de incio e outro de m, para representar os limites de um trecho entre duas linhas. Uma vrgula separa os dois endereos. Ento, a tarefa anterior de apagar as linhas ca 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/ 10,$ /couve/,$ /couve/,/vagem/ 1,$ da da da da da primeira linha at a linha que contm 'couve' linha 10 at o fim do arquivo linha que contm 'couve' at o fim do arquivo linha que contm 'couve' at a linha que contm 'vagem' primeira linha at a ltima (ou seja, todas)

Como pudemos notar, o trecho casado inclui as linhas de incio e m 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 m. 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/ { /um/ b /cinco/ b s/^/---/ } ;# ;# ;# ;# ;# ;# entre a linha 'um' e a linha 'cinco' ... se for a linha 'um', salte para o fim do script e processe a prxima linha (ou seja, no faa nada nesta) se for a linha 'cinco', salte para o fim do script e processe a prxima linha (ou seja, no faa nada nesta) 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 especicadas.

23

Dominando o SED - Endereo

Como negar um endereo, no aplicando comandos nele


Assim como podemos denir 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 modicador 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 ca: "Aplique os comandos do bloco em TODAS as linhas EXCETO as do endereo". Assim sendo, ca 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 modicador !, 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 especicar 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. Denida nossa rea de atuao, agora cou fcil! Por exemplo, para modicar 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 especcos. 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 cam 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 especicado acaba signicando: "Procure da primeira linha que tiver a letra 'o' at a ltima linha do texto". Para fazermos um s/primeira/ltima/ com este signicado, 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, camos 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 $! d $ g ;# guarde (sobrescrevendo) no RESERVA as linhas que contm 'o' ;# apague todas as linhas, menos a ltima ;# 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 especicar 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 diculdade enorme para se fazer isso num problema mais elaborado, alm do cdigo resultante car 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, m 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 cam especialmente obscuras. Anote em algum canto de seu crebro:
Se a mensagem de erro do sed aliengena, conra 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 signicados 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 ca: \/. 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 car escapando barras no nem um pouco prtico. Pior ainda se nosso padro estiver dentro de uma varivel, e no for to visvel o conito 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 dicilmente 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
s|...=|=|

confuso
s:...=:=:

s_$PWD_/TMP_ s!$PWD!/TMP!

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 nal. 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 car 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 enderelos 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 dene um bloco de comandos a ser aplicado no endereo especicado. Se no tiver endereo, o bloco ser aplicado para todas as linhas tornando desnecessrio o agrupamento. As linhas de incio e m 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 identicador 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 uxos 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 cando 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 uxos 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 ltro, que repassa o uxo de texto para a tela do computador, ns usurios tambm temos necessidades de armazenamento desse uxo. Seja para consulta posterior, para edio de arquivos (e no uxos) ou para registros e extrao de dados, importante guardamos o texto processado pelo sed em um arquivo. Mas sendo o sed um ltro de uxos, 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 uxo 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 signica 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 maiorque ">>". 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 nalmente 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 m 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 suciente. 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 especcas (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 nalizar 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 ltros, 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 "inplace", 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 cando 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 quem 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 desaador, 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 diculdade em identicar 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 car seu script sed. Com certeza cou 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: ca 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 identicao 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 --le, 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$ Xbc prompt$ XXc prompt$ XXX prompt$ s/X/./g prompt$ ... echo abc | sed -f a.sed echo abc | sed -e 's/b/a/' -f a.sed echo abc | sed -e 's/b/a/' -f a.sed -e 's/c/X/' cat x.sed 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 nal 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 cou 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 prompt$ chmod +x meu-script.sed 2 17:10 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 especicar 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 que muito bom (vai car, claro!) e voc o utilize com bastante freqncia, copie-o para o diretrio dos programas de verdade para no precisar mais do ./ para chamlo:
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 ca esperando at acabar todo o uxo 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 nal do texto. Isso torna possvel editar um uxo de texto interminvel. Pera, como assim interminvel? Sabe aqueles arquivos de registros ("log les"), que vo crescendo, crescendo indenidamente, 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 m do arquivo de registros. Como geralmente um arquivo de registros mostra mensagens variadas, s vezes at com excesso de informaes, torna-se necessrio o ltrarmos um pouco, e obter apenas as mensagens relevantes nossa necessidade no momento. Opa, falou em ltro? 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 uxos 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 nal 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 nal (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 nal (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 denio 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 diculdade? 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 m da linha.

70

Dominando o SED - Arquivo

Para contornar essa diculdade, 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, dicilmente ser corrigido pois muitos scripts foram feitos baseados nessas regras, e mud-las signica quebrar esses scripts.
72

Dominando o SED - Arquivo

Para nalizar 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 especicado 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 cou um pouco melhor que o anterior. Detalhes:

A linha gravada imediatamente, no espera o m 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 especicao 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 nal 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 identicados 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 signica perder todo o contedo anterior. Ento este arquivo no pode ser usado como arquivo de registros ("logle") 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 vericvel 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 desmisticar 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 m da linha, que o que vem antes da quebra da linha. Lembre-se da mquina de escrever, ao chegar ao nal 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 11 12 13 14 15 16 17 PATT:- um alicate de bico com cabo$ HOLD:$ COMM:/alicate/ N PATT:- um alicate de bico com cabo\nde borracha$ HOLD:$ COMM:s/\n/ / PATT:- um alicate de bico com cabo de borracha$ 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 cou o \n enado no meio das duas (L13). Da cou 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 2 3 4 PATT:um$ HOLD:$ COMM:N PATT:um\ndois$ 82

Dominando o SED - Quebra de linha 5 6 7 8 9 10 11 12 13 HOLD:$ COMM:s/\n/ / PATT:um dois$ HOLD:$ um dois PATT:trs$ HOLD:$ COMM:N 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 nal 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 nal 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, ca:
: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 innito? Se dissemos ao sed para sempre voltar ao comeo do script, ele far isso innitamente, 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 m do script:


_______________________________________ / \ | :inicio ; $<alguma-coisa> ; $! N ; s/\n/ / ; b inicio ^ | \__________________________________________/ v <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 m 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 m. Ei ei ei! Notaram que na ltima linha pularemos direto para o m 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 ca 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, nalizando 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 trabalhlo. Ainda na nossa rdua tarefa de juntar todas as linhas numa s, vamos ver como ca 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 nal do script. Mas fora isso, como funciona o lao?
1 2 3 4 5 6 7 8 9 10 11 PATT:um$ HOLD:$ COMM:H PATT:um$ HOLD:\num$ COMM:$ !d PATT:dois$ HOLD:\num$ COMM:H PATT:dois$ 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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 PATT:seis$ HOLD:\num\ndois\ntrs\nquatro\ncinco$ COMM:H PATT:seis$ HOLD:\num\ndois\ntrs\nquatro\ncinco\nseis$ COMM:$ !d PATT:seis$ HOLD:\num\ndois\ntrs\nquatro\ncinco\nseis$ COMM:g PATT:\num\ndois\ntrs\nquatro\ncinco\nseis$ HOLD:\num\ndois\ntrs\nquatro\ncinco\nseis$ COMM:s/\n/ /g PATT: um dois trs quatro cinco seis$ HOLD:\num\ndois\ntrs\nquatro\ncinco\nseis$ 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 nalmente 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 modicador 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 que 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, ca 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 tipogrca serve para denirmos os termos que identicam 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 cando 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, car 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, ca 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 renar esta expresso, mas por enquanto deixemos assim. Ento se j sabemos como identicar 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 car entre eles:
H ; g ; s/\n//

100

Dominando o SED - MAISCULAS/minsculas

Compondo o script todo ca:


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 signica 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 ca 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 ca 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 inui 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, especicar 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 denido 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 modicador 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 modicador I logo aps fechada a segunda barra delimitadora:
prompt$ sed '/root/I d' texto.txt

E tambm no comando s///, temos o mesmo modicador I, que pode ser includo no nal, junto com os outros modicadores 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 Obter o nmero da linha onde est a palava VERDE Remover todas as linhas em branco Remover todos os comentrios Comentar a linha que contm a palavra VERDE Desacentuar um arquivo Juntar todas as linhas numa s Remover todos os colchetes Remover todos os colchetes e seu contedo Tirar caracteres de controle como ^[33;43m (^[ Ctrl+v,ESC)
110 s/<[^>]*>//g /VERDE/= ; d /^ *$/d /^ *#/d /VERDE/s/^/#/ y// AAAAEEIOOUUCaaaaeeioouuc/ H ; $!d ; g ; s/\n/ /g s/[][]// s/\[[^]]*]// s/^[\[[0-9;]*m//

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 signica 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 tr -s ' ' tr -d '\012' wc -l uniq rev basename dirname cp | | | | | | | | | sed sed sed sed sed sed sed sed sed y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/ s/ \+/ /g H;$!d;g;s/\n//g -n $= x;G;/^\(.*\)\n\1$/d;g /\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.// s,.*/,, s,[^/]*$,, 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 ortogrcos e zemos 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