Este documento se propõe a ser um tutorial e um guia de consulta de
SED ao mesmo tempo.
Resumindo, o sed-HOWTO fala sobre SED.
Este documento pode (deve) ser distribuído à vontade.
Este documento é algo que eu estava me devendo há séculos: uma
documentação decente em português sobre o SED e seus detalhes.
É o sed-HOWTO, 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.
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 MUITA coisa a melhorar/acrescentar.
Qualquer sugestão é bem-vinda.
1. Sobre este documento
1.1. Descrição
Este documento NÃO abordará as expressões regulares, que são um tema
complexo, e embora façam parte da essência do SED, seu funcionamento
independe delas.
1.2. Anúncio
| formato | endereço | tamanho |
|---|---|---|
| online | http://aurelio.net/sed/sed-HOWTO/ | várias páginas |
| html | http://aurelio.net/sed/sed-HOWTO.html | (54k) |
| http://aurelio.net/sed/sed-HOWTO.pdf | (152k) | |
| txt | http://aurelio.net/sed/sed-HOWTO.txt | (48k) |
| sgml | http://aurelio.net/sed/sed-HOWTO.sgml | (52k) |
Meus agradecimentos sinceros àqueles que comentaram, enviaram sugestões e
correções, ou ajudaram na divulgação, via e-mail ou internet.
Vamos conhecer um pouco o SED, mostrar que ele não é o bicho de
SED cabeças que aparenta &:)
O SED é um editor de textos não interativo.
Ele pode editar automaticamente, sem interação do usuário, vários arquivos
seguindo um conjunto de regras especificadas.
Vem do inglês "Stream EDitor", ou seja, editor de fluxos (de texto).
Sendo um editor de textos não interativo, o SED é excelente para
desempenhar algumas tarefas, mas em outras seu uso não é aconselhado.
A característica principal do SED é poder editar arquivos automaticamente.
Então sempre que você precisar fazer alterações sistemáticas em vários
arquivos, o SED é 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 1999 onde era para ser 2000. 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 formato,
tendo saído como mm/dd/aaaa quando deveria ser dd/mm/aaaa. 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 SED mostra seu poder: alterações complexas em
vários arquivos.
Utilizando o SED, 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.
Nenhuma ferramenta é ideal para todas as tarefas, e o SED não é uma
exceção à regra.
Ele não é 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 vi ou o emacs e fazer a
alteração "na mão".
O SED 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 manipulador de texto e não uma
linguagem de uso geral.
Algumas estruturas complexas podem ser simuladas com alguma técnica, mas se
o seu programa em SED começou a inchar muito, é aconselhável reescrevê-lo
numa linguagem com mais recursos, como o perl.
O SED funciona como um filtro, por onde você passa um texto
O texto
Pense no SED como um processador de alimentos, dependendo da lâmina
utilizada, a batata sai cortada de uma maneira diferente &:)
A sintaxe genérica de um comando SED é:
Sendo que
Como notação tradicional, o que está
Ou seja, o SED lendo da entrada padrão o conteúdo do arquivo texto.txt
via duto
Um outro exemplo do SED com
E ainda, agora especificando um endereço para o comando
Ou seja, este comando imprime apenas a linha 5 do texto.txt
A execução do SED é 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 entrada padrão, via duto
E como dica geral SEMPRE coloque os comandos do SED entre aspas simples '',
para evitar que o shell os interprete erroneamente. Veja mais detalhes no
tópico Sed e shell
Com outra opção ainda, pode-se executar diretamente um arquivo com comandos
sed. Para mais informações, veja o tópico
Tornando arquivos sed executáveis
Ou num resumo rápido:
Aqui vão conhecimentos que você precisa assimilar para fazer um bom uso do
SED.
Normalmente o SED sempre imprime na saída padrão todas as linhas do
arquivo, modificadas ou não.
Veja o primeiro exemplo citado:
O comando
Temos como modificar este comportamento com a opção
Assim sendo, colocando o
Que resulta no conteúdo do arquivo, pois cada linha é impressa apenas uma
vez, devido ao comando
Ok, a explicação daquele 5 ali perdido vem a seguir no tópico:
O endereço &:)
O endereço serve para você dizer ao SED para aplicar um determinado
comando apenas nas linhas informadas. Este endereço pode ser descrito
direto como o número da linha, ou por parte de seu conteúdo (entre
Caso o endereço não seja informado, o comando SED será aplicado para
todas as linhas.
Por exemplo, referenciando a linha pelo seu número, como já foi visto
anteriormente:
Mas também poderia ser uma linha que tivesse uma palavra qualquer:
O comando
Como endereço, ainda se pode especificar um intervalo, como da linha
5 até a linha 10, ou da linha 5 até a linha que tiver a palavra
No endereço, temos um caractere especial, o
No SED da GNU, a partir da versão 3.02a(*), foi adicionada uma maneira
nova de especificar um endereço:
Que referencia a linha que contém a palavra
E pra finalizar, como já dito anteriormente, quando o comando não tem
endereço, é aplicado para todas as linhas:
(*) veja o tópico Nota sobre os adicionais gnu
A qualquer hora você pode abortar o comando SED com o comando
Isso é útil no nosso exemplo anterior de emular o comando head,
imprimindo apenas as 10 primeiras linhas do arquivo:
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:
No SED temos o modificador
Temos o comando head que imprime as 10 primeiras linhas de um arquivo.
Com as dicas já vistas, podemos fazer esta tarefa com o SED assim:
Ou ainda, podemos inverter a lógica e fazer:
A dica é sempre complementar a leitura mental com o inverso (entre
parênteses nos exemplos), ou seja, se o SED NÃO vai aplicar um comando em
determinadas linhas, isso quer dizer implicitamente que este comando
será aplicado em todas as outras linhas. É estranho, mas acostuma &:)
É possível aplicar vários comandos SED, em seqüência. Basta
separá-los por ponto-e-vírgula.
Este comando apaga as linhas 5, 10 e as que têm
Os comandos que recebem parâmetros (
Estes comandos devem ser separados dos restantes, sendo passados como
comandos isolados, pela opção de linha de comando
Este comando insere a frase
Outra maneira de especificar vários comandos (e a mais consistente e
garantida) é colocá-los num arquivo, um por linha. Veja o tópico
Colocando comandos sed num arquivo
Estes são conhecimentos que possivelmente surgirão como dúvidas em sua
cabeça após utilizar o SED por um tempo.
Com o SED 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
Para evitar isso coloque os comandos SED sempre entre aspas simples:
Salvo quando no meio do comando SED, existir algo que deva ser
interpretado, como uma variável por exemplo. Neste caso coloque os comandos
entre aspas duplas:
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
Colocando comandos sed num arquivo
É comum ao fazer um comando de substituição
Sendo a barra o delimitador do comando
Para evitar ter que ficar se escapando todas estas barras, basta lembrar
que o comando
Evitando-se de ter que ficar escapando as barras. A mesma dica vale para o
comando
E se precisássemos apagar as linhas que contém o
Para usarmos outro delimitador no endereço, basta escaparmos o
primeiro, que no caso abaixo é a vírgula:
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.
No SED da GNU, a partir da versão 3.02.80(*), vários escapes novos
foram adicionados e podem ser usados nas duas partes do comando
(*) veja o tópico Nota sobre os adicionais gnu
O procedimento comum quando se quer gravar num arquivo o resultado de um
comando SED, é o redirecionamento:
Mas é muito comum, ao alterarmos um arquivo, queremos gravar estas
alterações no próprio arquivo original. A tentativa intuitiva seria:
Mas é só fazer para ver. Além de não dar certo, você ainda perderá todo o
conteúdo do arquivo.
Isso acontece porque ao fazer o redirecionamento
Para evitar isso, voltamos a primeira tática de gravar o resultado num
outro arquivo, e depois o mais natural é mover o arquivo novo sobre o
original:
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 será perdido. 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, herdado do arquivo novo.
Para evitar isso, a abordagem mais ortodoxa e segura seria aplicar o
comando SED numa cópia e gravar o resultado no arquivo original via
redirecionamento:
Novamente, isso só é necessário com arquivos especiais, senão a solução com
o mv 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.
No SED da GNU, a partir da versão 3.02.80(*), foi adicionado o
Mas com outras versões do SED que não entendem este escape, a quebra de
linha deve ser inserida literalmente e deve ser escapada:
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 laço:
(*) veja o tópico Nota sobre os adicionais gnu
O comando para apagar linhas é o
O único detalhe nesta tarefa é especificar quais linhas você vai querer
apagar. Isso está completamente coberto no tópico O endereço
O jeito padrão do SED ser "ignore-case", é dizendo literalmente todas as
possibilidades, como em:
Para apagar todas as linhas que contêm a palavra
No SED da GNU, a partir da versão 3.01-beta1(*), foi adicionado o
modificador
Ou ainda:
(*) veja o tópico Nota sobre os adicionais gnu
Uma tarefa comum é incluir cabeçalho e rodapé num arquivo qualquer. O
SED possui um comando específico para ler arquivos, o
Para incluir o cabeçalho após a linha 1 e incluir o rodapé após a
última linha.
(*) a explicação do porquê das opções
O comando
Nosso similar em sed seria:
Gravar dados num arquivo também pode servir de espaço auxiliar caso o
espaço reserva não seja suficiente. Mas esta é uma opção drástica, não
tão flexível. Mais informações sobre o espaço reserva no tópico
Conhecendo os registradores internos
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.
Essa é simples, basta usar o comando
Note que o comando
No SED da GNU, a partir da versão 3.02a(*), é permitido que se coloque
o texto na mesma linha:
(*) veja o tópico Nota sobre os adicionais gnu
Similarmente a trocar por apenas uma linha, pode-se usar o comando
É claro, quando o comando começa a ficar grande desse jeito, é melhor
colocá-lo num arquivo.
detalhes sobre isso em Colocando comandos sed num arquivo
Mas melhor ainda é separar o comando SED do texto, colocando-o num
arquivo separado. Assim, quando se precisar alterar este texto, basta
editá-lo, sem mudar o comando SED, e sem precisar ficar colocando
Supondo que nosso texto explicativo do porquê da retirada do texto
pré-formatado foi gravado no arquivo desculpa.txt, utilizaremos o comando
Então acompanhe o que acontece: o primeiro comando será executado apenas na
linha
Ao chegar na linha que contém o
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 é
SED, pois será apenas um texto normal.
Note que sempre que o
obs.: talvez o
Aqui vão alguns exemplos de emulações de outros comandos usando-se o
SED:
Estes são conhecimentos necessários àqueles que fazem uso intensivo do
SED, fazendo programas grandes e/ou complexos.
No SED da GNU, a partir da versão 3.02.80(*), foi adicionada a opção
-u, que significa "unbuffered", ou seja, faz um uso minimalista dos
registradores, mostrando a saída o mais rápido possível, tornando possível
editar um fluxo interminável como o gerado por um tail -f.
Um exemplo prático seria mostrar apenas as mensagens do sistema relativas
às conexões ssh:
Cuidado com -nu perto de crianças! &:)
(*) veja o tópico Nota sobre os adicionais gnu
Como os comandos SED vão ficando extensos e complicados, é conveniente
colocá-los num arquivo, com estruturação e comentários.
Você pode espalhar os comandos por várias linhas, trocando o
Para dizer ao SED para utilizar aquele arquivo como fonte de comandos,
basta usar a opção
O interpretador de comandos mais utilizado (bash) sempre procura na
primeira linha de um arquivo instruções para executá-lo.
Se um arquivo é um programinha em shell, basta colocar
Na primeira linha para que o bash saiba que deve executá-lo com o
comando
E é claro, torná-lo executável:
E na linha de comando, chame-o normalmente:
O SED possui 2 registradores ("buffers") internos, que são usados para a
manipulação do texto.
Um deles é o espaço padrão ("pattern space"), que é o registrador
utilizado normalmente pelo SED. É nele que a linha a ser processada é
armazenada e manipulada.
O outro é o espaço reserva ("hold space"), que é um registrador auxiliar,
inicialmente vazio, que serve para guardar uma cópia da linha original,
parte dela, ou agrupar dados diversos de várias linhas.
Há comandos para fazer a troca de dados entre os dois registradores:
O anexando acima significa "não sobrescreve o conteúdo original", ou
seja, ele mantém o que já tem, e adiciona um
Um exemplo didático de uso do espaço reserva é ir guardando nele algumas
linhas do texto e mostrá-las depois no final do arquivo:
Ou seja, adicione no espaço reserva (comando
Como os registradores são a parte mais obscura do SED (mais por falta
de documentação do que por complexidade), merecem uma explicação bem
didática. Vamos lá.
Temos os dois registradores vazios:
(que daqui pra frente serão chamados apenas de padrão e reserva)
E um arquivo hipotético com o conteúdo:
(não são odiosos estes exemplos com frutas?)
E aplicaremos o comando:
Obtendo como resultado:
Vejamos o que aconteceu. Lida a primeira linha
O comando direcionado a ela é o
Como mais nenhum comando é relativo à linha
Beleza, agora ele vai processar a segunda linha, novamente a primeira coisa
é colocá-la no padrão, sobrescrevendo o que tinha antes:
O reserva, enquanto nenhum outro comando escrever nele, permanecerá o
mesmo. O comando direcionado à linha
Novamente, não há mais comandos a ser executados, então imprime na saída o
conteúdo do padrão: "laranja".
Indo para a terceira linha e colocando-a no padrão:
O comando dessa linha é o
Novamente, chegou ao fim, imprime o padrão: "abacaxi".
a próxima linha é a da
E agora vai ficar divertido, aplicando o comando
E a saída agora fica "melancia\nlaranja\nabacaxi", com o detalhe que o
SED troca estes
E finalmente, a última linha:
E para ela, o comando que troca o conteúdo dos 2 registradores, o
E mostra na saída o padrão, com duas linhas: "laranja" e "abacaxi".
Ufa! Depois dessa não venha me dizer que não sabe como funcionam os
registradores internos do SED &;)
Para uma representação gráfica dos fluxos e comandos que manipulam estes
registradores, veja o tópico Fluxos dos registradores internos
Veja explicação sobre estes registradores no tópico
Conhecendo os registradores internos
O SED 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
compatibilidade, pois seu programa SED não funcionará em UNIXes ou
outros sistemas que usem um SED 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.
1.4. Registro de mudanças
sgml2latex -o ps sed-HOWTO.sgml)
.tgz do ar
1.5. Agradecimentos
.*@conectiva
.*@lista_sed-br
.*@lista_sed-users
Carlos Alvsan
Eduardo Mendes
Rafael Steil
Rodrigo Bernardo Pimentel
Rubens Queiroz de Almeida & Dicas-l
Sérgio Bruder & .BR
Tiago Barros & senha.org
2. Conhecendo o sed
2.1. Descrição do sed
2.2. O que significa a palavra sed
2.3. Como saber se devo usar o sed
2.3.1. Quando usar o sed
2.3.2. Quando não usar o sed
2.3.2.1. Edição genérica de textos
2.3.2.2. Programação avançada
3. Perdendo o medo do sed
3.1. Como ele funciona
X e ele joga
na saída um texto Y.
X virou Y seguindo algumas regrinhas que você determinou.
3.2. Sua sintaxe
sed [opções] regras [arquivo]
regras tem a forma genérica de:
[endereço1 [, endereço2]] comando [argumento]
3.2.1. Exemplo
[entre colchetes] é opcional, então a
sintaxe SED mais simples que existe é sed regra como em:
prompt$ cat texto.txt | sed p
|, aplica o comando p para todas as linhas do arquivo, ou seja,
as duplica.
3.2.2. Outros exemplos
opções e recebendo um arquivo como parâmetro
seria:
prompt$ sed -n p texto.txt
p:
prompt$ sed -n 5p texto.txt
3.3. Como executá-lo
| ou redirecionamento <.
prompt$ sed 'p' texto.txt
prompt$ cat texto.txt | sed 'p'
prompt$ sed 'p' < texto.txt
4. Os comandos do sed
4.1. Descrição de todos os comandos
prompt$ man sed
prompt$ pinfo sed
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
4.2. Lista de todos os comandos por categoria
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
5. Conceitos básicos
5.1. Suprimindo a saída padrão
5.1.1. Saída normal
prompt$ sed 'p' texto.txt
p imprime a linha na saída padrão. Este exemplo duplica todas
as linhas do arquivo pois, além da impressão normal de cada linha, ainda é
aplicado o comando p em cada uma, que diz "imprima esta linha", fazendo
com que ela apareça duas vezes.
5.1.2. Saída suprimida
-n, que significa
"não imprima na saída, a não ser quando especificado com o comando p ou o
l.
-n, eliminamos o comportamento padrão de
"imprimir sempre na saída":
prompt$ sed -n 'p' texto.txt
p. Assim fica fácil entender como funciona o
exemplo já citado que imprime apenas a linha 5 de um arquivo:
prompt$ sed -n 5p texto.txt
5.2. O endereço
/barras/).
5.2.1. Endereço simples
prompt$ sed '5d' texto.txt
prompt$ sed '/estorvo/d' texto.txt
d apaga linhas segundo o endereço, então este comando
apagará todas as linhas que tiverem a palavra estorvo. Este exemplo tem o
funcionamento idêntico ao comando:
prompt$ grep -v estorvo texto.txt
5.2.2. Intervalo
estorvo:
prompt$ sed '5,10d' texto.txt
prompt$ sed '5,/estorvo/d' texto.txt
$ que referencia à
última linha do texto. Assim sendo, para apagar da linha 10 até o
final do texto, o comando é:
prompt$ sed '10,$d' texto.txt
5.2.3. Outros
prompt$ sed '/estorvo/,+3d' texto.txt
estorvo e mais as 3 linhas
seguintes.
prompt$ sed 'd' texto.txt
5.3. Interrompendo o processamento
q.
sed '10q' ao chegar na linha 10, pare.
sed '/^$/q' pare na primeira linha em branco que achar
5.4. Invertendo a lógica
! que inverte a lógica do comando, ou seja
!comando significa "não execute o comando". É meio estranho a primeira
vista, mas você tem que começar a pensar como o SED, e tudo se esclarece
&:)
sed -n '1,10p' imprima apenas da linha 1 até a 10
sed '11,$d' apague da linha 11 até o final
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)
5.5. Aplicando vários comandos de uma vez
5.5.1. Comandos normais
prompt$ sed '5d;10d;/estorvo/d' texto.txt
estorvo do arquivo
texto.txt.
5.5.2. Comandos com parâmetros
r, w, i, a, c), não aceitam
o ponto-e-vírgula como separador, pois este pode ser parte integrante do
parâmetro esperado.
-e:
prompt$ sed -e '1i começo de tudo' -e '5d' texto.txt
começo de tudo antes da primeira linha e
apaga a quinta linha do arquivo texto.txt.
5.5.3. Terceira via
6. Conceitos complementares
6.1. Sed e shell
$, \ e !, são interpretados pelo shell antes de chegarem ao
SED, modificando o comportamento esperado.
prompt$ sed 's/isso/aquilo/' texto.txt
prompt$ sed "s/$HOME/aquilo/" texto.txt
6.2. Usando outros delimitadores
6.2.1. No comando s
s/// conter uma
/ num dos dois lados do comando, como quando querendo substituir
/usr/local/bin por /usr/bin.
s as outras barras comuns devem
ser escapadas com a barra invertida \, para não serem confundidas com os
delimitadores normais, ficando o monstro a seguir:
prompt$ sed 's/\/usr\/local\/bin/\/usr\/bin/' texto.txt
s aceita qualquer 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:
prompt$ sed 's,/usr/local/bin,/usr/bin,' texto.txt
y.
6.2.2. No endereço
/usr/local/bin? Teríamos
que colocar o nome do diretório no endereço do comando d, voltando
com a festa dos escapes:
prompt$ sed '/\/usr\/local\/bin/d' texto.txt
prompt$ sed '\,/usr/local/bin,d' texto.txt
6.3. Escapes para caracteres especiais
s///:
\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
6.4. Gravando o resultado no mesmo arquivo
6.4.1. Problema inicial
prompt$ sed 'comando' texto.txt > texto-alterado.txt
prompt$ sed 'comando' texto.txt > texto.txt
>, o shell abre
imediatamente o arquivo referenciado, antes mesmo de começar a executar o
comando SED. E como este é um redirecionamento destrutivo > e não
incremental >>, se o arquivo já existir, ele será truncado, e seu
conteúdo perdido. A essa altura, o SED começará seu processamento já
lendo um arquivo texto.txt vazio, e aplicados qualquer comandos
SED num
arquivo vazio, o resultado será o próprio arquivo vazio.
6.4.2. Solução genérica
prompt$ sed 'comando' texto.txt > texto-alterado.txt
prompt$ mv texto-alterado.txt texto.txt
6.4.3. Solução segura
prompt$ cp -a texto.txt texto-tmp.txt
prompt$ sed 'comando' texto-tmp.txt > texto.txt
prompt$ rm texto-tmp.txt
7. Tarefas diversas
7.1. Como substituir alguma coisa por uma quebra de linha
\n
como escape válido dos dois lados do comando s///. Com isso a tarefa de
colocar cada palavra numa linha isolada, ou seja, trocar espaços em branco
por quebras de linha, fica trivial:
prompt$ sed 's/ /\n/g' texto.txt
prompt$ sed 's/ /\
prompt$ /g' texto.txt
prompt$ sed ':a;$!N;s/\n/ /g;ta'
7.2. Apagando linhas específicas
d.
7.3. Como ignorar maiúsculas e minúsculas
prompt$ sed '/[Rr][Oo][Oo][Tt]/d' texto.txt
root, ROOT, RooT
etc.
I no endereço e no comando s///, fazendo com que o
comando acima fique mais simples:
prompt$ sed '/root/Id' texto.txt
prompt$ sed 's/root/administrador/Ig' texto.txt
7.4. Lendo e gravando em arquivos externos
7.4.1. Lendo arquivos
r, então
basta(*):
prompt$ sed -e '1r cabecalho.txt' -e '$r rodape.txt' texto.txt
-e está no tópico
Aplicando vários comandos de uma vez
7.4.2. Gravando arquivos
w grava num arquivo a linha atual, ou melhor, o conteúdo do
espaço padrão. Por exemplo, você quer gravar num arquivo o resultado de
uma busca por linhas que contêm a palavra estorvo. A solução não-sed
seria:
prompt$ grep 'estorvo' texto.txt > estorvos.txt
prompt$ sed '/estorvo/w estorvos.txt' texto.txt
7.5. Trocando um trecho de texto por outro
7.5.1. Trocar várias linhas por uma
c, que "Coloca" um texto no lugar da
linha atual. A única complicação é definir o endereço, 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 <pre> e </pre>:
prompt$ sed '/<pre>/,/<\/pre>/c \
prompt$ aqui tinha texto pré-formatado' texto.html
c (assim como o a e o i) exige que o texto que
ele recebe como parâmetro esteja na linha seguinte, estando a quebra de
linha escapada com a barra invertida \
prompt$ sed '/<pre>/,/<\/pre>/c aqui tinha texto pré-formatado' texto.html
7.5.2. Trocar várias linhas por outras
c e
passar várias linhas para ele. O único detalhe é que todas as linhas devem
ser escapadas no final, menos a última:
prompt$ sed '/<pre>/,/<\/pre>/c \
prompt$ aqui tinha texto pré-formatado,\
prompt$ mas eu resolvi tirar.\
prompt$ porque?\
prompt$ porque sim' texto.html
\ no
final de cada linha.
r para lê-lo e o comando d para apagar o texto antigo:
prompt$ sed -e '/<\/pre>/r desculpa.txt' -e '/<pre>/,/<\/pre>/d' texto.html
</pre> que é o fechamento do trecho, então vamos esquecer dele por
enquanto. O segundo comando diz para apagar o trecho desde <pre> até
</pre>, então assim que começar o trecho, ele vai apagando, linha por
linha.
</pre>, o primeiro comando SED entra em
ação e lê o arquivo desculpa.txt, colocando seu conteúdo imediatamente
após a linha atual. Em seguida, o segundo comando apaga a linha </pre>,
completando a tarefa.
</pre> foi referenciado nos endereços, a
barra foi escapada, ficando <\/pre>. A explicação desse escape está em
Usando outros delimitadores
<pre></pre> não seja um exemplo dos mais didáticos, mas
não me veio algo mais comum à mente...
7.6. Emulando outros comandos
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 $=
8. Conceitos avançados
8.1. Monitorando um arquivo
prompt$ tail -f /var/log/messages | sed -nu '/sshd/p'
8.2. Colocando comandos sed num arquivo
; por quebras
de linha e colocar comentários precedidos de #. O exemplo de apagar
linhas ficaria:
# programa.sed: apaga algumas linhas
# apaga a 5ª linha
5d
# apaga a 10ª linha
10d
# apaga as linhas que contêm 'estorvo'
/estorvo/d
-f
prompt$ sed -f programa.sed texto.txt
8.3. Tornando arquivos sed executáveis
#!/bin/sh
/bin/sh. O mesmo funciona para qualquer outro interpretador,
como o SED. então para tornar um arquivos de comandos SED
executável basta colocar como primeira linha:
#!/bin/sed -f
prompt$ chmod +x programa.sed
prompt$ ./programa.sed texto.txt
prompt$ cat texto.txt | ./programa.sed
8.4. Conhecendo os registradores internos
8.4.1. Apresentação
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
\n (quebra de linha),
seguido do texto manipulado. Para entender melhor, veja o exemplo gráfico
a seguir.
8.4.2. Exemplo
prompt$ sed '/root/H;$g' /etc/passwd
H), as linhas que contêm a
palavra root e na última linha do arquivo (endereço $), recupere o
conteúdo do espaço reserva (comando g).
8.4.3. Exemplo gráfico
__________________ __________________
| | | |
| | | |
|__________________| |__________________|
espaço padrão espaço reserva
laranja
uva
abacaxi
melancia
mimosa
sed '/laranja/h ; /uva/g ; /abacaxi/H ; /melancia/G ; /mimosa/x'
laranja
laranja
abacaxi
melancia
laranja
abacaxi
laranja
abacaxi
laranja, ela é
imediatamente colocada no padrão para ser manipulada:
__________________ __________________
| | | |
| laranja | | |
|__________________| |__________________|
espaço padrão espaço reserva
h, que guarda uma cópia dela no
reserva:
__________________ __________________
| | | |
| laranja | -- h --> | laranja |
|__________________| |__________________|
espaço padrão espaço reserva
laranja, o SED dá por
encerrado o processamento dessa linha e imprime o conteúdo do padrão na
saída: "laranja".
__________________ __________________
| | | |
| uva | | laranja |
|__________________| |__________________|
espaço padrão espaço reserva
uva é o g, que pega o conteúdo do
reserva e o coloca no padrão, apagando o que estiver nele (neste caso:
uva):
__________________ __________________
| | | |
| laranja | <-- g -- | laranja |
|__________________| |__________________|
espaço padrão espaço reserva
__________________ __________________
| | | |
| abacaxi | | laranja |
|__________________| |__________________|
espaço padrão espaço reserva
H, que tal como o h, guarda o conteúdo do
padrão no reserva, com diferença que ele preserva o conteúdo já
existente dele, separando com um \n:
__________________ __________________
| | | |
| abacaxi | -- H --> | laranja\nabacaxi |
|__________________| |__________________|
espaço padrão espaço reserva
melancia:
__________________ __________________
| | | |
| melancia | | laranja\nabacaxi |
|__________________| |__________________|
espaço padrão espaço reserva
G, que pega o conteúdo
do reserva e anexa ao padrão:
____________________________ __________________
| | | |
| melancia\nlaranja\nabacaxi | <-G-- | laranja\nabacaxi |
|____________________________| |__________________|
espaço padrão espaço reserva
\n por quebras de linha na impressão. Então são 3
linhas na saída. Vá acompanhando com o resultado que já foi cantado
antecipadamente lá em cima.
__________________ __________________
| | | |
| mimosa | | laranja\nabacaxi |
|__________________| |__________________|
espaço padrão espaço reserva
x:
__________________ __________________
| | | |
| laranja\nabacaxi | <-- x ---> | mimosa |
|__________________| |__________________|
espaço padrão espaço reserva
8.4.4. Resumão
\n é o separador do conteúdo original com o anexo
\n vira quebra de linha
8.4.5. Fluxograma
9. Fluxogramas
9.1. Fluxos do texto
_________
w | | r
/------->| ARQUIVO |------->
| |_________|
______|______ SAÍDA
n | | p P l
ENTRADA ------->| S E D |------------------->
N |_____________| a i c
|
| d
\-------> /dev/null
D
9.2. Fluxos da execução dos comandos
_________
| |
______| próxima |<---\
/ | linha | |
| |_________| |
| |
v d D | n N
_____|______
| |
COMEÇO --------->| COMANDOS |----------> FIM DO PROGRAMA
|____________| q
| ^
b | t |
| |
| ___|______
| | |
\-->| marcação |
|__________|
9.3. Fluxos dos registradores internos
_________________ __________________
| |---- h H --->| |
| ESPAÇO PADRÃO |<--- x --->| ESPAÇO RESERVA |
|_________________|<--- g G ----|__________________|
10. Nota sobre os adicionais gnu