<!doctype linuxdoc system>
<article>
<title>sed-HOWTO
<author>Aurélio Marinho Jargas, verde (a) aurelio net
<date>v0.5 - 15 de Abril de 2003

<p>
<sect>Sobre este documento<p>

<!-- ____________________________________________________________________________- -->

<sect1>Descrição<p>

Este documento se propõe a ser um <bf>tutorial</bf> e um <bf>guia de consulta</bf> de
<em>SED</em> ao mesmo tempo.

<itemize>
<item><bf>tutorial</bf> porque ele vai lhe apresentando o <em>SED</em> aos poucos, explicando
  seu funcionamento e
<item><bf>guia de consulta</bf> porque ele tem dicas avançadas e descreve truques
  específicos que só serão assimilados e compreendidos executando-os na
  prática.
</itemize>
Este documento <bf>NÃO</bf> abordará as <em>expressões regulares</em>, que são um tema
complexo, e embora façam parte da essência do <em>SED</em>, seu funcionamento
independe delas.

Resumindo, o <em>sed-HOWTO</em> fala sobre <em>SED</em>.

Este documento pode (deve) ser distribuído <bf>à vontade</bf>.

<!-- ____________________________________________________________________________- -->

<sect1>Anúncio<p>

Este documento é algo que eu estava me devendo há séculos: uma
documentação decente em português sobre o <em>SED</em> e seus detalhes.

É o <em>sed-HOWTO</em>, um misto de tutorial e guia de referência, com
exemplos práticos. A idéia é que sirva tanto aos principiantes
quanto aos iniciados, abrangendo conceitos básicos e complexos.

<htmlurl url="http://aurelio.net/sed/sed-HOWTO" name="http://aurelio.net/sed/sed-HOWTO">

Convido todos a visitarem e dar uma lida.

Além da versão html, o documento está disponível em texto, sgml e pdf.
O sgml ainda pode ser convertido em info, dvi, tex, lyx, rtf e xml.

Além de uma explicação bem detalhada, "gráfica" e didática dos
registradores internos e seus comandos

Com certeza, ainda tem <bf>MUITA</bf> coisa a melhorar/acrescentar.
Qualquer sugestão é bem-vinda.

<!-- ____________________________________________________________________________- -->

<sect1>Onde encontrá-lo<p>

A casa oficial deste documento é na seção <em>SED</em> da página do aurélio.
Você pode consultá-lo <em>on-line</em> ou baixá-lo para leitura local em
quaisquer dos formatos seguintes:

<table><tabular ca="lcr">
formato<colsep>endereço<colsep>tamanho<rowsep>
online<colsep><htmlurl url="http://aurelio.net/sed/sed-HOWTO/" name="http://aurelio.net/sed/sed-HOWTO/"><colsep>várias páginas<rowsep>
html<colsep><htmlurl url="http://aurelio.net/sed/sed-HOWTO.html" name="http://aurelio.net/sed/sed-HOWTO.html"><colsep>(54k)<rowsep>
pdf<colsep><htmlurl url="http://aurelio.net/sed/sed-HOWTO.pdf" name="http://aurelio.net/sed/sed-HOWTO.pdf"><colsep>(152k)<rowsep>
txt<colsep><htmlurl url="http://aurelio.net/sed/sed-HOWTO.txt" name="http://aurelio.net/sed/sed-HOWTO.txt"><colsep>(48k)<rowsep>
sgml<colsep><htmlurl url="http://aurelio.net/sed/sed-HOWTO.sgml" name="http://aurelio.net/sed/sed-HOWTO.sgml"><colsep>(52k)<rowsep>
</tabular></table>


<!-- ____________________________________________________________________________- -->

<sect1>Registro de mudanças<p>

<itemize>
<item><bf>20030415 v0.5:</bf>
  <itemize>
  <item>listagem dos comandos adicionada em <bf><em>Descrição de todos os comandos</em></bf>
  <item>mudanças cosméticas, URLs atualizadas, s/endereçamento/endereço/g
  <item>adicionada versão HTML (tudo em uma página) e retirada a versão em
    PostScript (basta fazer <tt>sgml2latex -o ps sed-HOWTO.sgml</tt>)
  <item>retirado também o <tt>.tgz</tt> do ar
  <item>o txt2tags (<htmlurl url="http://txt2tags.sf.net" name="http://txt2tags.sf.net">) agora é o conversor utilizado
    para gerar o sed-HOWTO - acabaram os títulos em CAPSLOCK
  </itemize>
<p>
<item><bf>200110?? v0.4:</bf>
  <itemize>
  <item>documento disponibilizado agora também em ps e pdf
  <item>mais info na seção <bf><em>Anúncio</em></bf>, sobre os formatos novos
  </itemize>
<p>
<item><bf>20001203 v0.3:</bf>
  <itemize>
  <item>criada seção <bf><em>Trocando um trecho de texto por outro</em></bf>
  <item>criada seção <bf><em>Fluxos da execução dos comandos</em></bf>
  <item>criada seção <bf><em>Onde encontrá-lo</em></bf>
  <item>exemplo gráfico didático em <bf><em>Conhecendo os registradores internos</em></bf>
  <item>informações mais didáticas na seção <bf><em>Como ele funciona</em></bf>
  <item>documento disponibilizado em txt e sgml
  <item>várias correções pequenas nos textos
  </itemize>
<p>
<item><bf>20000913 v0.2:</bf>
  <itemize>
  <item>criada seção <bf><em>Anúncio</em></bf>
  <item>criada seção <bf><em>Registro de mudanças</em></bf>
  <item>criada seção <bf><em>Agradecimentos</em></bf>
  <item>disponibilizado este documento em HTML compactado
  <item>retirada entrada duplicada na seção <bf><em>Emulando outros comandos</em></bf>
  </itemize>
<p>
<item><bf>20000825 v0.1:</bf>
  <itemize>
  <item>1ª versão
  <item>disponibilização na internet
  </itemize>
</itemize>
<!-- ____________________________________________________________________________- -->

<sect1>Agradecimentos<p>

Meus agradecimentos sinceros àqueles que comentaram, enviaram sugestões e
correções, ou ajudaram na divulgação, via e-mail ou internet.

<tscreen><verb>
.*@conectiva
.*@lista_sed-br
.*@lista_sed-users

Carlos Alvsan
Eduardo Mendes
Rafael Steil
Rodrigo Bernardo Pimentel
Rubens Queiroz de Almeida &amp; Dicas-l
Sérgio Bruder &amp; .BR
Tiago Barros &amp; senha.org
</verb></tscreen>

<!-- ============================================================================= -->

<sect>Conhecendo o sed<p>

Vamos conhecer um pouco o <em>SED</em>, mostrar que ele não é o bicho de
<em>SED</em> cabeças que aparenta &amp;:)

<!-- ____________________________________________________________________________- -->

<sect1>Descrição do sed<p>

O <em>SED</em> é um editor de textos <bf>não interativo</bf>.

Ele pode editar automaticamente, sem interação do usuário, vários arquivos
seguindo um conjunto de regras especificadas.

<!-- ____________________________________________________________________________- -->

<sect1>O que significa a palavra sed<p>

Vem do inglês "Stream EDitor", ou seja, editor de fluxos (de texto).

<!-- ____________________________________________________________________________- -->

<sect1>Como saber se devo usar o sed<p>

Sendo um editor de textos não interativo, o <em>SED</em> é excelente para
desempenhar algumas tarefas, mas em outras seu uso não é aconselhado.

<sect2>Quando usar o sed<p>

A característica principal do <em>SED</em> é poder editar arquivos automaticamente.

Então sempre que você precisar fazer alterações sistemáticas em <bf>vários</bf>
arquivos, o <em>SED</em> é uma solução eficaz.

Por exemplo, você tem um diretório cheio de relatórios de vendas, e
descobriu que por um erro na geração, todas as datas saíram erradas, com o
ano de <bf>1999</bf> onde era para ser <bf>2000</bf>. Num editor de textos normal, você tem
que abrir os relatórios um por um e alterar o ano em todas as ocorrências.

Certo, isso não é tão complexo se o editor de textos possuir uma ferramenta
de procura e troca, também chamado de substituição.

Mas então suponhamos que o erro da data não seja o ano, e sim o <bf>formato</bf>,
tendo saído como <bf>mm/dd/aaaa</bf> quando deveria ser <bf>dd/mm/aaaa</bf>. Aqui não é
uma substituição e sim uma troca de lugares, e uma ferramenta simples de
procura e troca não poderá ajudar.

Esse é um caso típico onde o <em>SED</em> mostra seu poder: alterações complexas em
vários arquivos.

Utilizando o <em>SED</em>, a solução para este problema (que veremos adiante) é até
simples, bastando definir uma série de regras de procura e troca, e o
programa se encarregará de executá-las e arrumar os relatórios.

<sect2>Quando não usar o sed<p>

<bf>Nenhuma</bf> ferramenta é ideal para todas as tarefas, e o <em>SED</em> não é uma
exceção à regra.

<sect3>Edição genérica de textos<p>

Ele <bf>não</bf> é prático para ser utilizado como editor de textos de uso genérico.

Para escrever textos, ou alterar coisas simples, é mais rápido e fácil
abrir um editor de textos interativo como o <em>vi</em> ou o <em>emacs</em> e fazer a
alteração "na mão".

<sect3>Programação avançada<p>

O <em>SED</em> não é uma linguagem de programação completa, pois não possui
variáveis, funções matemáticas, interação com o sistema operacional, entre
outras limitações. Mas bem, ele é um <bf>manipulador de texto</bf> e não uma
linguagem de uso geral.

Algumas estruturas complexas podem ser simuladas com alguma técnica, mas se
o seu programa em <em>SED</em> começou a inchar muito, é aconselhável reescrevê-lo
numa linguagem com mais recursos, como o <em>perl</em>.

<!-- ============================================================================= -->

<sect>Perdendo o medo do sed<p>

<!-- ____________________________________________________________________________- -->

<sect1>Como ele funciona<p>

O <em>SED</em> funciona como um filtro, por onde você passa um texto <tt>X</tt> e ele joga
na saída um texto <tt>Y</tt>.

O texto <tt>X</tt> virou <tt>Y</tt> seguindo algumas regrinhas que você determinou.

Pense no <em>SED</em> como um processador de alimentos, dependendo da lâmina
utilizada, a batata sai cortada de uma maneira diferente &amp;:)

<itemize>
<item>o <em>SED</em> funciona como um filtro, ou conversor.
<p>
<item>o <em>SED</em> é orientado a linha, de cima para baixo, da esquerda para a direita.
<p>
<item>o <em>SED</em> lê uma linha da entrada padrão (STDIN) ou de um arquivo especificado,
  aplica os comandos de edição e mostra o resultado na saída padrão (STDOUT).
  vai para a próxima linha e repete o processo.
<p>
<item>o <em>SED</em> aceita endereços para os comandos.
<p>
<item>o <em>SED</em> aplica os comandos para todas as linhas caso um endereço não
  seja especificado.
<p>
<item>o <em>SED</em> faz uso intensivo de expressões regulares.
<p>
<item>o <em>SED</em> é macho &amp;:)
</itemize>
<!-- ____________________________________________________________________________- -->

<sect1>Sua sintaxe<p>

A sintaxe genérica de um comando <em>SED</em> é:

<tscreen><verb>
sed [opções] regras [arquivo]
</verb></tscreen>

Sendo que <tt>regras</tt> tem a forma genérica de:

<tscreen><verb>
[endereço1 [, endereço2]] comando [argumento]
</verb></tscreen>

<sect2>Exemplo<p>

Como notação tradicional, o que está <tt>&lsqb;entre colchetes]</tt> é opcional, então a
sintaxe <em>SED</em> mais simples que existe é <tt>sed regra</tt> como em:

<tscreen><verb>
prompt$ cat texto.txt | sed p
</verb></tscreen>

Ou seja, o <em>SED</em> lendo da entrada padrão o conteúdo do arquivo <em>texto.txt</em>
via duto <bf><tt>|</tt></bf>, aplica o comando <bf><tt>p</tt></bf> para todas as linhas do arquivo, ou seja,
as duplica.

<sect2>Outros exemplos<p>

Um outro exemplo do <em>SED</em> com <tt>opções</tt> e recebendo um arquivo como parâmetro
seria:

<tscreen><verb>
prompt$ sed -n p texto.txt
</verb></tscreen>

E ainda, agora especificando um <bf>endereço</bf> para o comando <bf><tt>p</tt></bf>:

<tscreen><verb>
prompt$ sed -n 5p texto.txt
</verb></tscreen>

Ou seja, este comando imprime apenas a <bf>linha 5</bf> do <em>texto.txt</em>

<!-- ____________________________________________________________________________- -->

<sect1>Como executá-lo<p>

A execução do <em>SED</em> é igual a de outro aplicativo qualquer de manipulação de
texto, aceitando como parâmetro um nome de arquivo, ou na falta deste, lê o
texto da <bf>entrada padrão</bf>, via duto <bf><tt>|</tt></bf> ou redirecionamento <bf><tt>&lt;</tt></bf>.

E como dica geral <bf>SEMPRE</bf> coloque os comandos do <em>SED</em> entre aspas simples '',
para evitar que o <em>shell</em> os interprete erroneamente. Veja mais detalhes no
tópico <bf><em>Sed e shell</em></bf>

<tscreen><verb>
prompt$ sed 'p' texto.txt
prompt$ cat texto.txt | sed 'p'
prompt$ sed 'p' &lt; texto.txt
</verb></tscreen>

Com outra opção ainda, pode-se executar diretamente um arquivo com comandos
sed. Para mais informações, veja o tópico
<bf><em>Tornando arquivos sed executáveis</em></bf>

<!-- ============================================================================= -->

<sect>Os comandos do sed<p>

<!-- ____________________________________________________________________________- -->

<sect1>Descrição de todos os comandos<p>

<tscreen><verb>
prompt$ man sed
prompt$ pinfo sed
</verb></tscreen>

Ou num resumo rápido:

<tscreen><verb>
Legenda:

[ARQUIVO]	arquivo ou fluxo de texto (via pipe) original a ser modificado
[TEXTO]		trecho de texto. pode ser uma palavra, uma linha,
		várias separadas por \n, ou mesmo um vazio.
[PADRÃO]	[TEXTO] contido no ESPAÇO PADRÃO


=	imprime o número da linha atual do [ARQUIVO]
#	inicia um comentário
!	inverte a lógica do comando
;	separador de comandos
,	separador de faixas de endereço
{	início de bloco de comandos
}	fim de bloco de comandos

s	substitui um trecho de texto por outro
y	traduz um caractere por outro

i	insere um texto antes da linha atual 
c	troca a linha atual por um texto
a	anexa um texto após a linha atual

g	restaura o [TEXTO] contido no ESPAÇO RESERVA (sobrescrevendo)
G	restaura o [TEXTO] contido no ESPAÇO RESERVA (anexando)
h	guarda o [PADRÃO] no ESPAÇO RESERVA (sobrescrevendo)
H	guarda o [PADRÃO] no ESPAÇO RESERVA (anexando)
x	troca os conteúdos dos ESPAÇO PADRÃO e RESERVA

p	imprime o [PADRÃO]
P	imprime a primeira linha do [PADRÃO]
l	imprime o [PADRÃO] mostrando caracteres brancos

r	inclui conteúdo de um arquivo antes da linha atual
w	grava o [PADRÃO] num arquivo

:	define uma marcação
b	pula até uma marcação 
t	pula até uma marcação, se o último s/// funcionou (condicional)

d	apaga o [PADRÃO]
D	apaga a primeira linha do [PADRÃO]
n	vai para a próxima linha
N	anexa a próxima linha no [PADRÃO]
q	finaliza o sed imediatamente

</verb></tscreen>

<!-- ____________________________________________________________________________- -->

<sect1>Lista de todos os comandos por categoria<p>

<tscreen><verb>
                         informações =
                          marcadores :
                         comentários #
                  comandos de edição s i c a y
           comandos de registradores g G h H x
               comandos de impressão p P l
                 comandos de arquivo r w
                       modificadores g i !
                         separadores ; -e \n
                   controle de fluxo b t d D n N q
                            endereço // ,
                         limitadores {} \(\)
             registradores dinâmicos \1 \2 ... \9
</verb></tscreen>

<!-- ============================================================================= -->

<sect>Conceitos básicos<p>

Aqui vão conhecimentos que você <bf>precisa</bf> assimilar para fazer um bom uso do
<em>SED</em>.

<!-- ____________________________________________________________________________- -->

<sect1>Suprimindo a saída padrão<p>

<sect2>Saída normal<p>

Normalmente o <em>SED</em> sempre imprime na <bf>saída padrão</bf> todas as linhas do
arquivo, modificadas ou não.

Veja o primeiro exemplo citado:

<tscreen><verb>
prompt$ sed 'p' texto.txt
</verb></tscreen>

O comando <bf><tt>p</tt></bf> imprime a linha na saída padrão. Este exemplo <bf>duplica</bf> todas
as linhas do arquivo pois, além da impressão normal de cada linha, ainda é
aplicado o comando <bf><tt>p</tt></bf> em cada uma, que diz "imprima esta linha", fazendo
com que ela apareça duas vezes.

<sect2>Saída suprimida<p>

Temos como modificar este comportamento com a opção <bf><tt>-n</tt></bf>, que significa
"não imprima na saída, a não ser quando especificado com o comando <bf><tt>p</tt></bf> ou o
<bf><tt>l</tt></bf>.

Assim sendo, colocando o <bf><tt>-n</tt></bf>, eliminamos o comportamento padrão de
"imprimir sempre na saída":

<tscreen><verb>
prompt$ sed -n 'p' texto.txt
</verb></tscreen>

Que resulta no conteúdo do arquivo, pois cada linha é impressa apenas uma
vez, devido ao comando <bf><tt>p</tt></bf>. Assim fica fácil entender como funciona o
exemplo já citado que imprime apenas a <bf>linha 5</bf> de um arquivo:

<tscreen><verb>
prompt$ sed -n 5p texto.txt
</verb></tscreen>

Ok, a explicação daquele <bf>5</bf> ali perdido vem a seguir no tópico:
<bf><em>O endereço</em></bf> &amp;:)

<!-- ____________________________________________________________________________- -->

<sect1>O endereço<p>

O endereço serve para você dizer ao <em>SED</em> para aplicar um determinado
comando <bf>apenas</bf> nas linhas informadas. Este endereço pode ser descrito
direto como o <bf>número</bf> da linha, ou por <bf>parte</bf> de seu conteúdo (entre
<tt>/barras/</tt>).

Caso o endereço não seja informado, o comando <em>SED</em> será aplicado para
<bf>todas</bf> as linhas.

<sect2>Endereço simples<p>

Por exemplo, referenciando a linha pelo seu número, como já foi visto
anteriormente:

<tscreen><verb>
prompt$ sed '5d' texto.txt
</verb></tscreen>

Mas também poderia ser uma linha que tivesse uma palavra qualquer:

<tscreen><verb>
prompt$ sed '/estorvo/d' texto.txt
</verb></tscreen>

O comando <bf><tt>d</tt></bf> apaga linhas segundo o endereço, então este comando
apagará todas as linhas que tiverem a palavra <tt>estorvo</tt>. Este exemplo tem o
funcionamento idêntico ao comando:

<tscreen><verb>
prompt$ grep -v estorvo texto.txt
</verb></tscreen>

<sect2>Intervalo<p>

Como endereço, ainda se pode especificar um <bf>intervalo</bf>, como da linha
5 até a linha 10, ou da linha 5 até a linha que tiver a palavra <tt>estorvo</tt>:

<tscreen><verb>
prompt$ sed '5,10d' texto.txt
prompt$ sed '5,/estorvo/d' texto.txt
</verb></tscreen>

No endereço, temos um caractere especial, o <bf><tt>$</tt></bf> que referencia à
<bf>última</bf> linha do texto. Assim sendo, para apagar da <bf>linha 10</bf> até o
<bf>final</bf> do texto, o comando é:

<tscreen><verb>
prompt$ sed '10,$d' texto.txt
</verb></tscreen>

<sect2>Outros<p>

No <em>SED</em> da GNU, a partir da versão <bf>3.02a</bf>(*), foi adicionada uma maneira
nova de especificar um endereço:

<tscreen><verb>
prompt$ sed '/estorvo/,+3d' texto.txt
</verb></tscreen>

Que referencia a linha que contém a palavra <tt>estorvo</tt> e mais as <bf>3</bf> linhas
seguintes.

E pra finalizar, como já dito anteriormente, quando o comando <bf>não</bf> tem
endereço, é aplicado para todas as linhas:

<tscreen><verb>
prompt$ sed 'd' texto.txt
</verb></tscreen>

(*) veja o tópico <bf><em>Nota sobre os adicionais gnu</em></bf>

<!-- ____________________________________________________________________________- -->

<sect1>Interrompendo o processamento<p>

A qualquer hora você pode <bf>abortar</bf> o comando <em>SED</em> com o comando <bf><tt>q</tt></bf>.

Isso é útil no nosso exemplo anterior de emular o comando <em>head</em>,
imprimindo apenas as 10 primeiras linhas do arquivo:

<tscreen><verb>
sed '10q'         ao chegar na linha 10, pare.
</verb></tscreen>

Ou ainda, para obter apenas os cabeçalhos de uma mensagem de e-mail, que
são separados do corpo da mensagem por uma linha em branco:

<tscreen><verb>
sed '/^$/q'       pare na primeira linha em branco que achar
</verb></tscreen>

<!-- ____________________________________________________________________________- -->

<sect1>Invertendo a lógica<p>

No <em>SED</em> temos o modificador <bf><tt>!</tt></bf> que <bf>inverte</bf> a lógica do comando, ou seja
<tt>!comando</tt> significa "não execute o comando". É meio estranho a primeira
vista, mas você tem que começar a pensar como o <em>SED</em>, e tudo se esclarece
&amp;:)

Temos o comando <em>head</em> que imprime as 10 primeiras linhas de um arquivo.
Com as dicas já vistas, podemos fazer esta tarefa com o <em>SED</em> assim:

<tscreen><verb>
sed -n '1,10p'    imprima apenas da linha 1 até a 10
sed '11,$d'       apague da linha 11 até o final
</verb></tscreen>

Ou ainda, podemos inverter a lógica e fazer:

<tscreen><verb>
sed '1,10!d'      NÃO apague da linha 1 até a 10 (ou seja, apague as outras)
sed -n '11,$!p'   NÃO imprima da linha 11 até o final (ou seja, imprima as outras)
</verb></tscreen>

A dica é sempre complementar a leitura mental com o inverso (entre
parênteses nos exemplos), ou seja, se o <em>SED</em> NÃO vai aplicar um comando em
determinadas linhas, isso quer dizer implicitamente que este comando
<bf>será aplicado</bf> em todas as outras linhas. É estranho, mas acostuma &amp;:)

<!-- ____________________________________________________________________________- -->

<sect1>Aplicando vários comandos de uma vez<p>

<sect2>Comandos normais<p>

É possível aplicar vários comandos <em>SED</em>, em <bf>seqüência</bf>. Basta
separá-los por ponto-e-vírgula.

<tscreen><verb>
prompt$ sed '5d;10d;/estorvo/d' texto.txt
</verb></tscreen>

Este comando apaga as linhas 5, 10 e as que têm <tt>estorvo</tt> do arquivo
<em>texto.txt</em>.

<sect2>Comandos com parâmetros<p>

Os comandos que recebem parâmetros (<bf><tt>r</tt></bf>, <bf><tt>w</tt></bf>, <bf><tt>i</tt></bf>, <bf><tt>a</tt></bf>, <bf><tt>c</tt></bf>), não aceitam
o ponto-e-vírgula como separador, pois este pode ser parte integrante do
parâmetro esperado.

Estes comandos devem ser separados dos restantes, sendo passados como
comandos isolados, pela opção de linha de comando <bf><tt>-e</tt></bf>:

<tscreen><verb>
prompt$ sed -e '1i começo de tudo' -e '5d' texto.txt
</verb></tscreen>

Este comando insere a frase <tt>começo de tudo</tt> antes da primeira linha e
apaga a quinta linha do arquivo <em>texto.txt</em>.

<sect2>Terceira via<p>

Outra maneira de especificar vários comandos (e a mais consistente e
garantida) é colocá-los num arquivo, um por linha. Veja o tópico
<bf><em>Colocando comandos sed num arquivo</em></bf>

<!-- ============================================================================= -->

<sect>Conceitos complementares<p>

Estes são conhecimentos que possivelmente surgirão como dúvidas em sua
cabeça após utilizar o <em>SED</em> por um tempo.

<!-- ____________________________________________________________________________- -->

<sect1>Sed e shell<p>

Com o <em>SED</em> sendo invocado na linha de comando, deve-se ter alguns cuidados
para evitar transtornos. O interpretador de comandos (shell), interpreta a
linha de comando antes de processá-la, então alguns caracteres especiais
como <bf><tt>$</tt></bf>, <bf><tt>\</tt></bf> e <bf><tt>!</tt></bf>, são interpretados pelo shell <bf>antes</bf> de chegarem ao
<em>SED</em>, modificando o comportamento esperado.

Para evitar isso coloque os comandos <em>SED</em> <bf>sempre</bf> entre aspas simples:

<tscreen><verb>
prompt$ sed 's/isso/aquilo/' texto.txt
</verb></tscreen>

Salvo quando no meio do comando <em>SED</em>, existir algo que deva ser
interpretado, como uma variável por exemplo. Neste caso coloque os comandos
entre aspas duplas:

<tscreen><verb>
prompt$ sed "s/$HOME/aquilo/" texto.txt
</verb></tscreen>

Ou ainda, para evitar completamente a interpretação do shell, sem se
preocupar com aspas, coloque os comandos sed num arquivo. Veja o tópico
<bf><em>Colocando comandos sed num arquivo</em></bf>

<!-- ____________________________________________________________________________- -->

<sect1>Usando outros delimitadores<p>

<sect2>No comando s<p>

É comum ao fazer um comando de substituição <bf><tt>s///</tt></bf> conter uma
<bf><tt>/</tt></bf> num dos dois lados do comando, como quando querendo substituir
<tt>/usr/local/bin</tt> por <tt>/usr/bin</tt>.

Sendo a barra o delimitador do comando <bf><tt>s</tt></bf> as outras barras comuns devem
ser escapadas com a barra invertida <bf><tt>\</tt></bf>, para não serem confundidas com os
delimitadores normais, ficando o monstro a seguir:

<tscreen><verb>
prompt$ sed 's/\/usr\/local\/bin/\/usr\/bin/' texto.txt
</verb></tscreen>

Para evitar ter que ficar se escapando todas estas barras, basta lembrar
que o comando <bf><tt>s</tt></bf> aceita <bf>qualquer</bf> delimitador, sendo a barra apenas um
padrão de referências históricas. Então, neste caso, poderíamos escolher
outro delimitador como por exemplo a vírgula:

<tscreen><verb>
prompt$ sed 's,/usr/local/bin,/usr/bin,' texto.txt
</verb></tscreen>

Evitando-se de ter que ficar escapando as barras. A mesma dica vale para o
comando <bf><tt>y</tt></bf>.

<sect2>No endereço<p>

E se precisássemos apagar as linhas que contém o <tt>/usr/local/bin</tt>? Teríamos
que colocar o nome do diretório no endereço do comando <bf><tt>d</tt></bf>, voltando
com a festa dos escapes:

<tscreen><verb>
prompt$ sed '/\/usr\/local\/bin/d' texto.txt
</verb></tscreen>

Para usarmos outro delimitador no endereço, basta escaparmos o
primeiro, que no caso abaixo é a vírgula:

<tscreen><verb>
prompt$ sed '\,/usr/local/bin,d' texto.txt
</verb></tscreen>

Confusão de delimitadores com o texto a ser procurado é muito comum de
acontecer, então se algo não está funcionando como deveria, olhe com
cuidado para ver se não há conflitos entre eles.

<!-- ____________________________________________________________________________- -->

<sect1>Escapes para caracteres especiais<p>

No <em>SED</em> da GNU, a partir da versão <bf>3.02.80</bf>(*), vários escapes novos
foram adicionados e podem ser usados nas duas partes do comando <bf><tt>s///</tt></bf>:

<tscreen><verb>
   \a      beep             (apito)
   \f      form-feed        (avança linha)
   \n      newline          (quebra de linha)
   \r      carriage-return  (retorno de carro)
   \t      hTAB             (tabulação horizontal)
   \v      vTAB             (tabulação vertical)
   \oNNN   o caractere de valor octal NNN
   \dNNN   o caractere de valor decimal NNN
   \xNN    o caractere de valor hexadecimal NN
</verb></tscreen>

(*) veja o tópico <bf><em>Nota sobre os adicionais gnu</em></bf>

<!-- ____________________________________________________________________________- -->

<sect1>Gravando o resultado no mesmo arquivo<p>

<sect2>Problema inicial<p>

O procedimento comum quando se quer gravar num arquivo o resultado de um
comando <em>SED</em>, é o redirecionamento:

<tscreen><verb>
prompt$ sed 'comando' texto.txt &gt; texto-alterado.txt
</verb></tscreen>

Mas é muito comum, ao alterarmos um arquivo, queremos gravar estas
alterações no <bf>próprio</bf> arquivo original. A tentativa intuitiva seria:

<tscreen><verb>
prompt$ sed 'comando' texto.txt &gt; texto.txt
</verb></tscreen>

Mas é só fazer para ver. Além de não dar certo, você ainda perderá <bf>todo</bf> o
conteúdo do arquivo.

Isso acontece porque ao fazer o redirecionamento <bf><tt>&gt;</tt></bf>, o <tt>shell</tt> abre
imediatamente o arquivo referenciado, antes mesmo de começar a executar o
comando <em>SED</em>. E como este é um redirecionamento destrutivo <bf><tt>&gt;</tt></bf> e não
incremental <bf><tt>&gt;&gt;</tt></bf>, se o arquivo já existir, ele será truncado, e seu
conteúdo perdido. A essa altura, o <em>SED</em> começará seu processamento já
lendo um arquivo <em>texto.txt</em> vazio, e aplicados qualquer comandos
<em>SED</em> num
arquivo vazio, o resultado será o próprio arquivo vazio.

<sect2>Solução genérica<p>

Para evitar isso, voltamos a primeira tática de gravar o resultado num
outro arquivo, e depois o mais natural é <bf>mover</bf> o arquivo novo sobre o
original:

<tscreen><verb>
prompt$ sed 'comando' texto.txt &gt; texto-alterado.txt
prompt$ mv texto-alterado.txt texto.txt
</verb></tscreen>

Para a grande maioria dos casos, isso é suficiente, mas convém aqui lembrar
que caso o arquivo 'texto.txt' possua atributos especiais, grupo diferente
do padrão do usuário, ou referências (links, simbólicos ou não) para outros
arquivos, tudo isso <bf>será perdido</bf>. Ao mover o arquivo recém-criado, com os
atributos padrão do sistema, sobre o original, este perderá seus atributos
e ficará com os padrões do sistema, <bf>herdado</bf> do arquivo novo.

<sect2>Solução segura<p>

Para evitar isso, a abordagem mais ortodoxa e segura seria aplicar o
comando <em>SED</em> numa cópia e gravar o resultado no arquivo original via
redirecionamento:

<tscreen><verb>
prompt$ cp -a texto.txt texto-tmp.txt
prompt$ sed 'comando' texto-tmp.txt &gt; texto.txt
prompt$ rm texto-tmp.txt
</verb></tscreen>

Novamente, isso só é necessário com arquivos especiais, senão a solução com
o <em>mv</em> pode ser usada. Mas é importante ter em mente esta outra maneira e
principalmente saber o porque de utilizá-la, sendo este conhecimento
aplicável a qualquer outro comando do sistema que leia e grave arquivos.

<!-- ============================================================================= -->

<sect>Tarefas diversas<p>

<!-- ____________________________________________________________________________- -->

<sect1>Como substituir alguma coisa por uma quebra de linha<p>

No <em>SED</em> da GNU, a partir da versão <bf>3.02.80</bf>(*), foi adicionado o <bf><tt>\n</tt></bf>
como escape válido dos dois lados do comando <bf><tt>s///</tt></bf>. Com isso a tarefa de
colocar cada palavra numa linha isolada, ou seja, trocar espaços em branco
por quebras de linha, fica trivial:

<tscreen><verb>
prompt$ sed 's/ /\n/g' texto.txt
</verb></tscreen>

Mas com outras versões do <em>SED</em> que não entendem este escape, a quebra de
linha deve ser inserida <bf>literalmente</bf> e deve ser escapada:

<tscreen><verb>
prompt$ sed 's/ /\
prompt$ /g' texto.txt
</verb></tscreen>

Como curiosidade, a operação inversa, de colocar todas as linhas de um
arquivo numa linha só, já é mais trabalhosa e utiliza o conceito de <em>laço</em>:

<tscreen><verb>
prompt$ sed ':a;$!N;s/\n/ /g;ta'
</verb></tscreen>

(*) veja o tópico <bf><em>Nota sobre os adicionais gnu</em></bf>

<!-- ____________________________________________________________________________- -->

<sect1>Apagando linhas específicas<p>

O comando para apagar linhas é o <bf><tt>d</tt></bf>.

O único detalhe nesta tarefa é especificar <bf>quais</bf> linhas você vai querer
apagar. Isso está  completamente coberto no tópico <bf><em>O endereço</em></bf>

<!-- ____________________________________________________________________________- -->

<sect1>Como ignorar maiúsculas e minúsculas<p>

O jeito padrão do <em>SED</em> ser "ignore-case", é dizendo literalmente todas as
possibilidades, como em:

<tscreen><verb>
prompt$ sed '/[Rr][Oo][Oo][Tt]/d' texto.txt
</verb></tscreen>

Para apagar todas as linhas que contêm a palavra <tt>root</tt>, <tt>ROOT</tt>, <tt>RooT</tt>
etc.

No <em>SED</em> da GNU, a partir da versão <bf>3.01-beta1</bf>(*), foi adicionado o
modificador <bf><tt>I</tt></bf> no endereço e no comando <bf><tt>s///</tt></bf>, fazendo com que o
comando acima fique mais simples:

<tscreen><verb>
prompt$ sed '/root/Id' texto.txt
</verb></tscreen>

Ou ainda:

<tscreen><verb>
prompt$ sed 's/root/administrador/Ig' texto.txt
</verb></tscreen>

(*) veja o tópico <bf><em>Nota sobre os adicionais gnu</em></bf>

<!-- ____________________________________________________________________________- -->

<sect1>Lendo e gravando em arquivos externos<p>

<sect2>Lendo arquivos<p>

Uma tarefa comum é incluir cabeçalho e rodapé num arquivo qualquer. O
<em>SED</em> possui um comando específico para ler arquivos, o <bf><tt>r</tt></bf>, então
basta(*):

<tscreen><verb>
prompt$ sed -e '1r cabecalho.txt' -e '$r rodape.txt' texto.txt
</verb></tscreen>

Para incluir o cabeçalho após a linha <bf>1</bf> e incluir o rodapé após a
<bf>última</bf> linha.

(*) a explicação do porquê das opções <bf><tt>-e</tt></bf> está no tópico
<bf><em>Aplicando vários comandos de uma vez</em></bf>

<sect2>Gravando arquivos<p>

O comando <bf><tt>w</tt></bf> grava num arquivo a linha atual, ou melhor, o conteúdo do
<em>espaço padrão</em>. Por exemplo, você quer gravar num arquivo o resultado de
uma busca por linhas que contêm a palavra <tt>estorvo</tt>. A solução não-sed
seria:

<tscreen><verb>
prompt$ grep 'estorvo' texto.txt &gt; estorvos.txt
</verb></tscreen>

Nosso similar em sed seria:

<tscreen><verb>
prompt$ sed '/estorvo/w estorvos.txt' texto.txt
</verb></tscreen>

Gravar dados num arquivo também pode servir de <bf>espaço auxiliar</bf> caso o
<em>espaço reserva</em> não seja suficiente. Mas esta é uma opção drástica, não
tão flexível. Mais informações sobre o <em>espaço reserva</em> no tópico
<bf><em>Conhecendo os registradores internos</em></bf>

<!-- ____________________________________________________________________________- -->

<sect1>Trocando um trecho de texto por outro<p>

Uma tarefa que parece simples mas confunde, é trocar um trecho de texto,
como um parágrafo inteiro por exemplo, por outro trecho, independente do
número de linhas de ambos.

<sect2>Trocar várias linhas por uma<p>

Essa é simples, basta usar o comando <bf><tt>c</tt></bf>, que "Coloca" um texto no lugar da
linha atual. A única complicação é definir o <em>endereço</em>, para aplicar
o comando apenas nas linhas desejadas. Por exemplo, vamos colocar uma frase
no lugar de uma área de texto pré-formatado num documento HTML. Esta área é
delimitada pelos identificadores <bf><tt>&lt;pre&gt;</tt></bf> e <bf><tt>&lt;/pre&gt;</tt></bf>:

<tscreen><verb>
prompt$ sed '/&lt;pre&gt;/,/&lt;\/pre&gt;/c \
prompt$ aqui tinha texto pré-formatado' texto.html
</verb></tscreen>

Note que o comando <bf><tt>c</tt></bf> (assim como o <bf><tt>a</tt></bf> e o <bf><tt>i</tt></bf>) <bf>exige</bf> que o texto que
ele recebe como parâmetro esteja na linha seguinte, estando a quebra de
linha escapada com a barra invertida <bf><tt>\</tt></bf>

No <em>SED</em> da GNU, a partir da versão <bf>3.02a</bf>(*), é permitido que se coloque
o texto na mesma linha:

<tscreen><verb>
prompt$ sed '/&lt;pre&gt;/,/&lt;\/pre&gt;/c aqui tinha texto pré-formatado' texto.html
</verb></tscreen>

(*) veja o tópico <bf><em>Nota sobre os adicionais gnu</em></bf>

<sect2>Trocar várias linhas por outras<p>

Similarmente a trocar por apenas uma linha, pode-se usar o comando <bf><tt>c</tt></bf> e
passar várias linhas para ele. O único detalhe é que todas as linhas devem
ser <bf>escapadas</bf> no final, menos a última:

<tscreen><verb>
prompt$ sed '/&lt;pre&gt;/,/&lt;\/pre&gt;/c \
prompt$ aqui tinha texto pré-formatado,\
prompt$ mas eu resolvi tirar.\
prompt$ porque?\
prompt$ porque sim' texto.html
</verb></tscreen>

É claro, quando o comando começa a ficar grande desse jeito, é melhor
colocá-lo num arquivo.
detalhes sobre isso em <bf><em>Colocando comandos sed num arquivo</em></bf>

Mas melhor ainda é separar o comando <em>SED</em> do texto, colocando-o num
arquivo separado. Assim, quando se precisar alterar este texto, basta
editá-lo, sem mudar o comando <em>SED</em>, e sem precisar ficar colocando <bf><tt>\</tt></bf> no
final de cada linha.

Supondo que nosso texto explicativo do porquê da retirada do texto
pré-formatado foi gravado no arquivo <em>desculpa.txt</em>, utilizaremos o comando
<bf><tt>r</tt></bf> para lê-lo e o comando <bf><tt>d</tt></bf> para apagar o texto antigo:

<tscreen><verb>
prompt$ sed -e '/&lt;\/pre&gt;/r desculpa.txt' -e '/&lt;pre&gt;/,/&lt;\/pre&gt;/d' texto.html
</verb></tscreen>

Então acompanhe o que acontece: o primeiro comando será executado apenas na
linha <tt>&lt;/pre&gt;</tt> que é o fechamento do trecho, então vamos esquecer dele por
enquanto. O segundo comando diz para apagar o trecho desde <tt>&lt;pre&gt;</tt> até
<tt>&lt;/pre&gt;</tt>, então assim que começar o trecho, ele vai apagando, linha por
linha.

Ao chegar na linha que contém o <tt>&lt;/pre&gt;</tt>, o primeiro comando <em>SED</em> entra em
ação e lê o arquivo <em>desculpa.txt</em>, colocando seu conteúdo imediatamente
após a linha atual. Em seguida, o segundo comando apaga a linha <tt>&lt;/pre&gt;</tt>,
completando a tarefa.

Esta segunda solução é mais difícil de entender e implementar, mas é muito
mais prática caso a alteração do texto a ser colocado seja freqüente, além
destas alterações poderem ser feitas por alguém que nem saiba o que é
<em>SED</em>, pois será apenas um texto normal.

Note que sempre que o <tt>&lt;/pre&gt;</tt> foi referenciado nos <em>endereços</em>, a
barra foi escapada, ficando <tt>&lt;\/pre&gt;</tt>. A explicação desse escape está em
<bf><em>Usando outros delimitadores</em></bf>

<bf>obs.:</bf> talvez o <tt>&lt;pre&gt;&lt;/pre&gt;</tt> não seja um exemplo dos mais didáticos, mas
não me veio algo mais comum à mente...

<sect1>Emulando outros comandos<p>

Aqui vão alguns exemplos de emulações de outros comandos usando-se o
<em>SED</em>:

<tscreen><verb>
comando      |  emulação
-------------+----------------------------------------
cat          |  sed :
head         |  sed 10q
grep         |  sed /padrão/!d
grep -v      |  sed /padrão/d
tac          |  sed 1!G;h;$!d
tail -1      |  sed $!d
tr A-Z a-z   |  sed y/ABCDEF...UVWXYZ/abcdef...uvwxyz/
wc -l        |  sed -n $=

</verb></tscreen>

<!-- ============================================================================= -->

<sect>Conceitos avançados<p>

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

<!-- ____________________________________________________________________________- -->

<sect1>Monitorando um arquivo<p>

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

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

<tscreen><verb>
prompt$ tail -f /var/log/messages | sed -nu '/sshd/p'
</verb></tscreen>

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

(*) veja o tópico <bf><em>Nota sobre os adicionais gnu</em></bf>

<!-- ____________________________________________________________________________- -->

<sect1>Colocando comandos sed num arquivo<p>

Como os comandos <em>SED</em> vão ficando extensos e complicados, é conveniente
colocá-los <bf>num arquivo</bf>, com estruturação e comentários.

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

<tscreen><verb>
    # programa.sed: apaga algumas linhas

    # apaga a 5ª linha
    5d

    # apaga a 10ª linha
    10d

    # apaga as linhas que contêm 'estorvo'
    /estorvo/d
</verb></tscreen>

Para dizer ao <em>SED</em> para utilizar aquele arquivo como fonte de comandos,
basta usar a opção <bf><tt>-f</tt></bf>

<tscreen><verb>
prompt$ sed -f programa.sed texto.txt
</verb></tscreen>

<!-- ____________________________________________________________________________- -->

<sect1>Tornando arquivos sed executáveis<p>

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

Se um arquivo é um programinha em <em>shell</em>, basta colocar

<tscreen><verb>
#!/bin/sh
</verb></tscreen>

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

<tscreen><verb>
#!/bin/sed -f
</verb></tscreen>

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

<tscreen><verb>
prompt$ chmod +x programa.sed
</verb></tscreen>

E na linha de comando, chame-o normalmente:

<tscreen><verb>
prompt$ ./programa.sed texto.txt
prompt$ cat texto.txt | ./programa.sed
</verb></tscreen>

<!-- ____________________________________________________________________________- -->

<sect1>Conhecendo os registradores internos<p>

<sect2>Apresentação<p>

O <em>SED</em> possui 2 registradores ("buffers") internos, que são usados para a
manipulação do texto.

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

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

Há comandos para fazer a troca de dados entre os dois registradores:
<tscreen><verb>
  h      guarda no espaço reserva
  H      guarda (anexando) no espaço reserva

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

  x      troca os conteúdos dos 2 registradores
</verb></tscreen>

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

<sect2>Exemplo<p>

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

<tscreen><verb>
prompt$ sed '/root/H;$g' /etc/passwd
</verb></tscreen>

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

<sect2>Exemplo gráfico<p>

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

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

<tscreen><verb>
             __________________                __________________
            |                  |              |                  |
            |                  |              |                  |
            |__________________|              |__________________|
               espaço padrão                     espaço reserva
</verb></tscreen>

E um arquivo hipotético com o conteúdo:
(não são odiosos estes exemplos com frutas?)
<tscreen><verb>
laranja
uva
abacaxi
melancia
mimosa
</verb></tscreen>

E aplicaremos o comando:

<tscreen><verb>
sed '/laranja/h ; /uva/g ; /abacaxi/H ; /melancia/G ; /mimosa/x'
</verb></tscreen>

Obtendo como resultado:
<tscreen><verb>
laranja
laranja
abacaxi
melancia
laranja
abacaxi
laranja
abacaxi
</verb></tscreen>

Vejamos o que aconteceu. Lida a primeira linha <tt>laranja</tt>, ela é
imediatamente colocada no <em>padrão</em> para ser manipulada:
<tscreen><verb>
             __________________                __________________
            |                  |              |                  |
            |      laranja     |              |                  |
            |__________________|              |__________________|
               espaço padrão                     espaço reserva
</verb></tscreen>

O comando direcionado a ela é o <bf><tt>h</tt></bf>, que guarda uma cópia dela no
<em>reserva</em>:
<tscreen><verb>
             __________________                __________________
            |                  |              |                  |
            |      laranja     |   -- h --&gt;   |      laranja     |
            |__________________|              |__________________|
               espaço padrão                     espaço reserva
</verb></tscreen>

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

Beleza, agora ele vai processar a segunda linha, novamente a primeira coisa
é colocá-la no <em>padrão</em>, sobrescrevendo o que tinha antes:
<tscreen><verb>
             __________________                __________________
            |                  |              |                  |
            |        uva       |              |      laranja     |
            |__________________|              |__________________|
               espaço padrão                     espaço reserva
</verb></tscreen>

O <em>reserva</em>, enquanto nenhum outro comando escrever nele, permanecerá o
mesmo. O comando direcionado à linha <tt>uva</tt> é o <bf><tt>g</tt></bf>, que pega o conteúdo do
<em>reserva</em> e o coloca no <em>padrão</em>, apagando o que estiver nele (neste caso:
<tt>uva</tt>):
<tscreen><verb>
             __________________                __________________
            |                  |              |                  |
            |      laranja     |   &lt;-- g --   |      laranja     |
            |__________________|              |__________________|
               espaço padrão                     espaço reserva
</verb></tscreen>

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

Indo para a terceira linha e colocando-a no <em>padrão</em>:
<tscreen><verb>
             __________________                __________________
            |                  |              |                  |
            |      abacaxi     |              |      laranja     |
            |__________________|              |__________________|
               espaço padrão                     espaço reserva
</verb></tscreen>

O comando dessa linha é o <bf><tt>H</tt></bf>, que tal como o <bf><tt>h</tt></bf>, guarda o conteúdo do
<em>padrão</em> no <em>reserva</em>, com diferença que ele preserva o conteúdo já
existente dele, separando com um <bf><tt>\n</tt></bf>:
<tscreen><verb>
             __________________                __________________
            |                  |              |                  |
            |      abacaxi     |   -- H --&gt;   | laranja\nabacaxi |
            |__________________|              |__________________|
               espaço padrão                     espaço reserva
</verb></tscreen>

Novamente, chegou ao fim, imprime o <em>padrão</em>: "abacaxi".
a próxima linha é a da <tt>melancia</tt>:
<tscreen><verb>
             __________________                __________________
            |                  |              |                  |
            |     melancia     |              | laranja\nabacaxi |
            |__________________|              |__________________|
               espaço padrão                     espaço reserva
</verb></tscreen>

E agora vai ficar divertido, aplicando o comando <bf><tt>G</tt></bf>, que pega o conteúdo
do <em>reserva</em> e anexa ao <em>padrão</em>:
<tscreen><verb>
        ____________________________           __________________
       |                            |         |                  |
       | melancia\nlaranja\nabacaxi |  &lt;-G--  | laranja\nabacaxi |
       |____________________________|         |__________________|
               espaço padrão                    espaço reserva
</verb></tscreen>

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

E finalmente, a última linha:
<tscreen><verb>
             __________________                __________________
            |                  |              |                  |
            |      mimosa      |              | laranja\nabacaxi |
            |__________________|              |__________________|
               espaço padrão                     espaço reserva
</verb></tscreen>

E para ela, o comando que troca o conteúdo dos 2 registradores, o <bf><tt>x</tt></bf>:
<tscreen><verb>
             __________________                __________________
            |                  |              |                  |
            | laranja\nabacaxi |  &lt;-- x ---&gt;  |      mimosa      |
            |__________________|              |__________________|
               espaço padrão                     espaço reserva
</verb></tscreen>

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

Ufa! Depois dessa não venha me dizer que não sabe como funcionam os
<em>registradores internos</em> do <em>SED</em> &amp;;)

<sect2>Resumão<p>

<itemize>
<item>cada linha nova lida é colocada (sobrescrevendo) no <em>espaço padrão</em>
<item>uma vez colocado algo no <em>espaço reserva</em>, fica lá até ser sobrescrito
<item>o <bf><tt>\n</tt></bf> é o separador do conteúdo original com o anexo
<item>na saída, o <bf><tt>\n</tt></bf> vira quebra de linha
<item>registradores são simples! &amp;;)
</itemize>
<sect2>Fluxograma<p>

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

<!-- ============================================================================= -->

<sect>Fluxogramas<p>

<sect1>Fluxos do texto<p>

<tscreen><verb>
                                          _________
                                    w    |         |   r
                                /-------&gt;| ARQUIVO |-------&gt;
                                |        |_________|
                          ______|______                       SAÍDA
                    n    |             |           p P l
        ENTRADA  -------&gt;|    S E D    |-------------------&gt;
                    N    |_____________|           a i c
                                |
                                |   d
                                \-------&gt; /dev/null
                                    D

</verb></tscreen>

<sect1>Fluxos da execução dos comandos<p>

<tscreen><verb>
                   _________
                  |         |
            ______| próxima |&lt;---\
           /      |  linha  |    |
           |      |_________|    |
           |                     |
           v                 d D | n N
                            _____|______
                           |            |
        COMEÇO   ---------&gt;|  COMANDOS  |----------&gt; FIM DO PROGRAMA
                           |____________|  q
                             |       ^
                           b | t     |
                             |       |
                             |    ___|______
                             |   |          |
                             \--&gt;| marcação |
                                 |__________|


</verb></tscreen>

<sect1>Fluxos dos registradores internos<p>

<tscreen><verb>
             _________________               __________________
            |                 |---- h H ---&gt;|                  |
            |  ESPAÇO PADRÃO  |&lt;---  x  ---&gt;|  ESPAÇO RESERVA  |
            |_________________|&lt;--- g G ----|__________________|


</verb></tscreen>

Veja explicação sobre estes registradores no tópico
<bf><em>Conhecendo os registradores internos</em></bf>

<!-- ____________________________________________________________________________- -->

<!-- ============================================================================= -->

<sect>Nota sobre os adicionais gnu<p>

O <em>SED</em> da GNU, atualmente é o utilizado pela maioria das distribuições de
Linux e é o que tem mais funcionalidades novas.

Mas o preço de se usar essas funcionalidades é que se perde em
<bf>compatibilidade</bf>, pois seu programa <em>SED</em> não funcionará em UNIXes ou
outros sistemas que usem um <em>SED</em> que não o da GNU.

Para a grande maioria dos usuários isso não fará diferença pois geralmente
trabalham com apenas um tipo de sistema operacional, mas o recado fica
dado.

<!-- ____________________________________________________________________________- -->

<sect>Onde obter mais informações<p>

Informações em português:
<itemize>
<item><htmlurl url="http://aurelio.net/sed" name="http://aurelio.net/sed">
<item><htmlurl url="http://www.lrv.ufsc.br/wmaker/sed_ptBR.html" name="http://www.lrv.ufsc.br/wmaker/sed_ptBR.html">
</itemize>
Documentação em inglês:
<itemize>
<item><htmlurl url="http://www.cornerstonemag.com/sed/sed1line.txt" name="http://www.cornerstonemag.com/sed/sed1line.txt">
<item><htmlurl url="http://www.cornerstonemag.com/sed/sedfaq.html" name="http://www.cornerstonemag.com/sed/sedfaq.html">
<item><htmlurl url="http://www.dreamwvr.com/sed-info/sed-faq.html" name="http://www.dreamwvr.com/sed-info/sed-faq.html">
<item><htmlurl url="http://www.rtfiber.com.tw/~changyj/sed" name="http://www.rtfiber.com.tw/~changyj/sed">
<item><htmlurl url="http://www.math.fu-berlin.de/~leitner/sed/tutorial.html" name="http://www.math.fu-berlin.de/~leitner/sed/tutorial.html">
</itemize>
Última versão em desenvolvimento do sed:
<itemize>
<item><htmlurl url="ftp://alpha.gnu.org/gnu/sed" name="ftp://alpha.gnu.org/gnu/sed">
</itemize>

<!-- sgml code generated by txt2tags 1.5-dev0415 (http://txt2tags.sf.net) -->
<!-- cmdline: txt2tags -t sgml -t sgml /home/verde/pessoal/verde666.org/sed/sed-HOWTO.t2t -->
</article>
