Sed - Introdução ao SED - Part I

Novembro 2016


Este documento é uma introdução à pratica e a utilização do editor « SED », que tenta cobrir algumas funcionalidades bastante desconhecidas, para não dizer "quase desconhecidas", que fazem de "SED" uma ferramenta indispensável na caixa de ferramentas de qualquer Linuxiano desejoso de romper com os problemas de tratamento de texto via um console e um Shell.

[ Parte II]
[ Parte III]

Apresentação


Sed significa "Stream EDitor" quer dizer "editor de fluxo", e mais precisamente « editor de fluxo linha ». De sua concepção e de seu modo de funcionamento, Sed é um editor não interativo.
Igual ao editor "ed" - de onde ele saiu e que se encontra ainda nas distribuições atuais - e contrariamente aos outros editores como vi, emacs, Nedit, Xedit, etc., que funcionam em uma página de texto afixado na tela, Sed age em uma só linha por vez.
Nos seus inícios o editor "Ed" se viu dotado de um comando que trabalhava em seu flux standard ae não sobre um arquivo, capaz de afixar todas as linhas contendo uma expressão regular. Este comando em que a sintaxe se escreve sob a "g/re/p" (global/regular expressão/print) dará origem ao utilitário "grep". Algum tempo depois uma nova implementação de uma versão de « ed » é lançada, trabalhando unicamente sobre o fluxo de entrada standard tirando suas instruções de um arquivo de scripts. Esta versão foi batizada Stream Editor, mais conhecida sob o nome de « Sed ».
O editor de flux Sed lê linhas de um ou vários arquivos depois de entrada standard, encadeia comandos lidos também a partir da entrada standard sob a forma de expressões(comandos de edição ) ou depois de um arquivo texto (script), e escreve o resultado do tratamento sobre a saída standard.

Poder-se-ia resumir o mecanismo de funcionamento de Sed desta maneira:
  • leitura de uma linha sobre um fluxo de entrada (uma linha sendo delimitada por um caractere de nova linha );
  • tratamento da linha em função dos diversos comandos lidos ;
  • afixagem (ou non) do resultado sobre a saída standard (tela );
  • passage à la linha suivante.


Notemos que para selecionar a ou as linhas sobra a qual ou quais elas devem operar, os comandos aceitam números de linhas, dos intervalos, ou ainda das expressões regulares (notadas RE ou regex).

Introdução


Sed toma suas instruções (comandos) a partir da linha de comandos ou a partir de um arquivo (script) e aplica cada instrução, na ordem de seu aparecimento, em cada linha em entrada. Assim que cada instrução foi aplicada na 1a linha de entrada, a linha é afixada (ou não, de acordo com suas necessidades ) na saída standard (na tela, ou redirigida em um arquivo ) e Sed procede então a leitura e ao tratamento da linha seguinte e assim por diante até o final do arquivo de entrada (a menos que ele encontre uma instrução de saída explicita ).
Este mecanismo se chama "ciclo". Entende-se por ciclo o tratamento dos dados apresentados no spaço por exemplo dos comandos que compões o script. Como padrão um ciclo corresponde a:
  • A adição no espaço de trabalho de uma linha em entrada (uma linha sendo delimitada pelo caracter fim de linha. (\n))
  • Normalmente o espaço de trabalho deve ser vazio, a menos que um comando « D » tenha terminado o clicle precedente (neste caso o ciclo repartira com os dados restantes no espaço de trabalho ).
  • Sed aplicaria então os comandos (tirados de um script ou a partir da linha de comando ) referente aos dados presentes no espaço de trabalho, seqüencialmente, e assim que tiver chegado ao script, copiará os dados tratados até a saída standard, salvo indicação com a opção "-n" e apagará o espaço de trabalho. Todos os dados enviados até a saída standard ou um arquivo, são seguidos por um caractere de final de linha (\n).
  • Carregamento de uma nova linha ou saída se o final do arquivo é atingido.


Tentemos ilustrar com a ajuda de um organograma o funcionamento a través de um script simples que apaga as linhas vazias de um arquivo e aqueles que comportam somente um caractere "quadrado" (#) no início da linha. Para tanto eis um exemplo de arquivo que comporta para a circunstância algumas linhas vazias, alguns quadrados sozinhos, dos quais um em recuo e não em início e duas linhas com diversos quadrados para a continuidade:

O arquivo:
# 
# 
 # 
## 
# Isto é um comentário 

# Eis outro 
# 

# 
# 
### 
# E outro 


# 

# 
# E um último para a estrada 
#
O script nele mesmo é relativamente simples. Eis sobre uma só linha :
sed -e '/^$/d;/^#$/d'

E em um arquivo script :
#! /bin/sed -f 

/^$/d   # apaga-se as linhas vazias  
/^#$/d # apaga-se as linhas que não comportam mais do que um caractere « quadrado »
           #+ encontrando-se no início de linha e nada mais atrás 
E o organograma:

Sintaxe

Sintaxe geral


sed [-opções] [comando] [<arquivo(s)>] 
sed [-n [-e comando] [-f script] [-i[.extensão]] [l [cesure]] rsu] [<comando>] [<arquivo(s)>]

Sintaxe de um comando


O endereçamento de uma ou mais linhas por alguns meios é facultativo para qualquer comando
[endereço[,endereço]][!]comando[argumentos]

Aliás, em conjunto de comandos podem ser aplicados a uma linha ou intervalo de linhas contornando por chaves.
[endereço [,]]{ 
comando1 
comando2 
comando3 
}

Note que estes comandos podem ser entre chaves sobre uma só linha com a condição de ser separadas por um ponto e vírgula (;).
[endereço[,endereço]]{comando1; comando2; comando3}

Endereçamento


Sed pode endereço diretamente uma linha (ou um intervalo) por seu número de linha ou pela correspondência com uma expressão regular que tem como alvo um motivo (padrãoa/modelo) definido.

Um ponto de exclamação (!) depois de um número de linha, um motivo ou uma expressão regular excluirá esta linha (ou intervalo) do tratamento a efetuar.

Este endereçamento pode se efetuar sob as seguintes formas:
num
  • O número da linha
    • sed -n 3p fich.txt

inicio~não
  • Todas as linhas (pas) partindo do início.
    • sed -n 1~2p fich.txt

$
  • A última linha do arquivo fornecido em entrada ou de cada arquivo se as opções "-i" ou "-s" foram especificadas
    • sed -n '$ p' fich.txt
    • sed -ns '$ p' fich*

/exp/
  • Todas as linhas colocadas em correspondência com a expressão regular exp
    • sed -n '/est/p' fich2.txt

\#exp#
  • Todas as linhas colocadas em correspondência com a expressão regular exp precisando utilizar como delimitador o caractere "#" (quadrado) no lugar e espaço do limitador padrão.
    • sed -n '\#est#p' fich2.txt

num1,num2
  • Todas as linhas compreendidas entre num1 e num2. Si num2 vinha a ser inferior à num1, só num1 é afixado
    • sed -n '3,6 p' fich.txt

/exp1/,/exp2/
  • Todas as linhas de exp1 e exp2, incluindo as linhas contendo exp1 e exp2. Se o intervalo contém duas expressões são repetidas várias vezes, sed instruções aplicáveis a cada intervalo sucessivo. No entanto, se exp2 não for encontrado, as instruções são aplicadas a cada linha a partir de exp1 até o final do arquivo.
    • sed -n '/comentário1/,/comentário2/ p' fich2.txt

num,/exp/
/exp/,num
  • Todas as linhas entre o número de linha e uma expressão regular (ou vice-versa). Em "exp num, / /", mas se exp não for encontrado, as instruções são aplicadas a cada linha a partir de digital até o final do arquivo. Em "exp /, num" Se num for inferior ao número da linha correspondente a exp, somente a linha exp é afixada.
    • sed -n '2,/comentário2/ p' fich2.txt
    • sed -n '/comentário1/,8 p' fich2.txt

As opções (parâmetros )


Sed acceita as opções (parâmetros) em entrada, pouco numerosos, e os mais utilizados são "-n", "-e" et "-i".


-n, --quiet, --silent
  • Solicitação implícita a não afixar o estado da memória principal (memória tampão). No interior de um script , a notação se fará desta maneira "#n" (um signo quadrado seguido do caracter "n") e devera se encontrar sobre a 1ª linha do script.

-e script, --expressão=script
  • Permite de encadear diversos comandos na continuidade

-f arquivo-script, *--file=arquivo-script
  • Leitura dos comandos depois do arquivo designado -i[SUFFIXE], --in-place[=SUFFIXE]
  • Edição em lugar do arquivo. Oferece também a possibilidade de fazer um backup adicionando uma extensão (-i.BAK)

--posix
  • Desativar todas as extensões GNU.

-r, --regexp-extended
  • Utilização da sintaxe das expressões regulares alastradas (ERE)

-s, --separate
  • Se diversos arquivos são fornecidos em entrada, tratá-los antes como uma só e mesma página.

-u, --unbuffered
  • Carregar quantidades mínimas de dados desde os arquivos de entrada e liberar os tampões de saída mais comum. --help
  • Afixar esta ajuda e sair --versão
  • Afixar as informações de versão do software e sair.

Os comandos


Veremos nos capítulos que seguem os comandos usados por Sed. Alguns deles podem parecer simples e de uso comum como um todo, do que outros, menos conhecidos, é verdade, a sua utilização e implementação de scripts sed pode ser mais difícil para ver a sintaxe e implementação, mas para dar outra dimensão a esta ferramenta relegada a simples filtro ...

Alguns comandos endereçamento admitem uma multi-linha ( intervalo ), Enquanto que outros não toleram somente um endereço, até mesmo nenhum para uma minoria. Esses recursos serão notificados para cada comando.

Os comandos básicos 1


São agrupados neste capítulo os comandos mais conhecidos do editor Sed e relativamente simples de emprego.

#
Comentário (nenhum endereço autorizado)
  • O caractere # (quadrado) começa o comentário e isto até o final da linha. Ele pode encontrar-se na mesma linha que um comando.


Se os dois primeiros caracteres de um script sed são "#n", a opção "-n" (no-autoprint) é então forçada. Então se seu script deve imperativamente iniciar por uma linha de comentário que começa pela letra "n" minúscula, queira utilizar um "N" maiúsculo ou inserir um espaço entre o quadrado (#) e o "n".

q quit
fachar (um endereço autorizado)
  • Feche sed sem proceder a nenhum outro comando nem avaliar outra entrada. A linha corrente continua na memória principal é afixada a menos que a opção "-n" tenha sido empregada.
    • sed '3q' fich.txt

d delete
apagar (intervalo de endereço autorizado)
  • Apaga o registro corrente e inicia um novo ciclo.
    • sed '3d' fich.txt

p print
afixagem (intervalo de endereço autorizado)
  • Exibe na tela o registro atual ( workspace ). Ele não exclui a área de trabalho e não muda ao desenrolar do script. Este comando é usado sempre em conjunto com o "n", caso contrário, a exibição da linha é duplicada. ( Prefirir a segunda forma que melhor se adapatada pois o script termina quando o motivo ou a linha encontrada for exibida na saída padrão, sem continuar a ver o resto do arquivo)
    • sed -n '3p' fich.txt
    • sed -n '3{p;q}' fich.txt

n next-line
linha seguinte (intervalo d'endereço autorizado)
  • Substitui o registro no atual espaço de trabalho pela linha seguinte sem começar um novo ciclo. A linha substituída é enviada para a saída standard.
    • eco -e "AAA\nBBB\nCCC\nDDD" | sed -n '/BBB/ {n;p;q}'

{ ... }
comandos groupées (intervalo de endereço autorizado)
  • O emprego das chaves permite agrupar certos comandos a efetuar sobre um endereço ou um espaço endereços. É inútil protegê-los por um caractere backslash como é o caso para o emprego das expressões regulares indicando um número de repetições.
    • eco -e "AAA\nBBB\nCCC\nDDD" | sed -n '/BBB/ {n;s/C/Z/2p}'

s substituições
O comando de substituição (intervalo de endereço autorizado)
  • O comando de substituição "s" é sem dúvidas o comando mais utilizado do filtro sed. Sua sintaxe é muito simples:
    •  's/modelo/substituição/bandeira(x)'
  • Seu princípio de base é muito simples também: se um motivo corresponde à correspondente à cadeia em evidencia pelo modelo ou a expressão regular é encontrada, substituí-la pela cadeia de substituição pela cadeia de substituição, considerando as bandeiras eventuais, se presentes..
  • No mecanismo de substituição é preciso distinguir duas partes seguidamente referenciadas LHS (Left Hand Side = lado esquerdo) que corresponde à cadeia buscada e RHS (Right Hand Side = lado direito) correspondente à cadeia de substituição.
  • A mesma coisa pode-se dizer da parte esquerda (busca) aceita a sintaxe dos BRE (Basic Regular Expressão, expressões regulares básicas ), a parte direita (substituição ) quanto à ela não aceita mais do que três valores que podem ser interpolados:
    • o caractere & (esperluette)
    • as referências traseiras \1 (de 1 à 9)
    • as opções \U,\u,\L,\l et \E


Para interpretar literalmente um « & » ou um anti-slash « \ » é preciso os prefixos por um anti-slash :
\& ou \\

flags


As bandeiras ou atributos

O comando de substituição (s) pode ser seguido de um ou vários atributos/bandeiras (flags em inglês). Certas combinações não podem ser associadas como o atributo « g » "g" (global) e uma nona ocorrência (N) o que seria uma incoerência absoluta. Na mesma ordem de idéias, o atributo "w" deve ser o último da lista.

g global
  • Efetua a substituição de todas as ocorrências em correspondência, pelo motivo ou pela expressão regular.
eco "AAAAA" | sed 's/A/B/' BAAAA eco "AAAAA" | sed 's/A/B/g' BBBBB
N nona ocorrência
  • Substitui unicamente a nona ocorrência em correspondência pelo motivo ou pela expressão regular.

 eco "AAAAA" | sed 's/A/B/3' 
 AABAA 

p print (affichage)
  • Se uma substituição aconteceu, então afixar o registro corrente . Necessita a presença da opção "-n".

 $ var="linha1\nlinha2\nlinha3\nlinha4\nlinha5" 
 $ eco -e "$var" 
 linha1 
 linha2 
 linha3 
 linha4 
 linha5 

 $ eco -e "$var" | sed '3 s/e3/e n° 3/' 
 linha1 
 linha2 
 linha n° 3 
 linha4 
 linha5 

 $ eco -e "$var" | sed -n '3 s/e3/e n° 3/' 

 $ eco -e "$var" | sed '3 s/e3/e n° 3/p' 
 linha1 
 linha2 
 linha n° 3 
 linha n° 3 
 linha4 
 linha5 

 $ eco -e "$var" | sed -n '3 s/e3/e n° 3/p' 
 linha n° 3 


w arquivo - Write (escritura em um arquivo)
  • Se uma substituição aconteceu, entãi escrever o registro corrente no arquivo especificado. Somente um espaço é aceito entre o atributo "w" e o nome do arquivo.

  
 $ var="linha1\nlinha2\nlinha3\nlinha4\nlinha5" 
 $ eco -e "$var" | sed -n '3 s/e3/e n° 3/pw fich.out' 

e evaluate (avaliação)
  • Permite fazr executar um comando pelo shell e de substituir o resultado com o motivo em correnpondência, unicamente se uma correspondência foi estabelecida.


Exemplo 1 :
 $ eco $var 
 linha1\nlinha2\nlinha3\nlinha4\nlinha5\nlinha6\nlinha7\nlinha8\nlinha9 
 $ eco $A 
 Bom dia 
 $ eco -e "$var" | sed 's/.*5/eco '$A'/e' 
 linha1 
 linha2 
 linha3 
 linha4 
 Bom dia 
 linha6 
 linha7 
 linha8 
 linha9 
 $ 

Exemplo 2 :
 $ cat plop 
 0x00000000 0          root      777 
 0x00000000 65537      user1  600 
 0x00000000 98306      user1  600 
  
 $ eco -e "$var" | sed 's/.*5/cat plop/e' 
 linha1 
 linha2 
 linha3 
 linha4 
 0x00000000 0          root      777 
 0x00000000 65537      user1  600 
 0x00000000 98306      user1  600 
 linha6 
 linha7 
 linha8 
 linha9 
 $   
Discussão em relação no fórum

I case-Insensitive
  • Permite ignorar a quebra na instalação da correspondência do motivo
      
$ eco "Bom dia" | sed 's/Bom dia/Salut/' Bom dia $ eco "Bom dia" | sed 's/Bom dia/Oi/I' Oi
M
  • A M modificador para a correspondência da expressão regular é uma nova extensão do GNU sed, que tem o efeito de coincidir com o personagem e o caracter ^ $ ( para além da seu <comportamento original </ital >), respectivamente, com uma seqüência vazia após a outra Linha, e uma cadeia vazia antes de uma nova Linha. Já havia caracteres especiais \ ' e '(<ital> em modo básico ou expressões regulares ) que põem em correspondência o início e o final do buffer. M é a sua multi-Linhas.


Para tentar tornar mais simplesse for normal a área de trabalho contém uma Linha lida como entrada. Ourtras podem ser adicionadas ao espaço de trabalho através da utilização de comandos como N, G, x, etc. Todas estas Linhas no espaço de trabalho são separadas pela Linha final "\ n", mas são vistas por sed como uma única linha, cujo início ocorreu antes da primeira linha e se terminando no final da última linha. Com a bandeira "M" cada caractere representa o início (^) e fim ($) da linha recomeça de novo se pode-se dizer assim, seu significado original e fato coincide com o início e o fim de cada linha a cada linha localizada no espaço de trabalho.


Eis um exemplo oilustrando o emprego da bandeira (flag) "M" :

1° caso :
 $ eco -e "foo\nbar" | sed 'N;s/^.*$//' 
 $ 

Neste primeiro caso, ^ et $ apontam o início e o fim do buffer que depois da aplicação do comando "N" contém "foo\nbar$", e a expressão regular validada, pois tudo o que se encontra entre os dois caracteres simbolizando o início (^) e o fim ($) sem considerar o caractere representando o fim da linha "\n"

2° caso :
 $ eco -e "foo\nbar" | sed 'N;s/^.*$//M' 
 bar 
 $ 


Neste 2° caso, ^ e $ apontam o início e o fim da 1° linha no buffer, que como anteriormente depois da aplicação do comando "N" contém "foo\nbar$", mas com a diferença que a expressão regular validada unicamente os caracteres que se encontram com o caractere de fim de linha "\n"

3° caso :
 $ eco -e "foo\nbar\nfoobar\nbarfoo" | sed -e ':loup; N; $! b loup; s/^.*$//M3' 
 foo 
 bar 
  
 barfoo 
 $ 

Neste 3° caso, o buffer depois da execução do comando "N" (no interior de um loup tendo por efeito de carregar a integralidade das linhas no buffer ), se parece a "foo\nbar\nfoobar\nbarfoo$" e a substituição se aplica somente à 3° linha materializada pelo caractere "\n".

Eis 2 autros exemplos :

O 1° :
 $  eco -e "foo\nfoo\nfoo\nbar\nfoo" |  sed 'N;/bar$/s/^/>/Mg;P;D' 
 foo 
 foo 
 >foo 
 >bar 
 foo 
 $ 

No exemplo aqui acima, 2 linhas são carregadas no espaço de trabalho, se no fim do buffer não acaba por "bar", então 1° linha do buffer é afixada (P), pois apagada (D), e retoma-se a execução do script com o carregamento da linha seguinte (na continuidade desta ficando na buffer) onde se verifica denovo a correspondência com a expressão regular. Se a correspondência é estabelecida, junta-se uma seta para a direita (>) no início da linha, na continuidade da 1° linha do buffer é afixada (P) depois apagada (D) e retoma-se a execução do script...
Le 2nd :
 $ eco -e "foo\nfoo" |  sed 'N;s/^/>/;s/\n/\n>/g' 
 >foo 
 >foo 
  
 $ eco -e "foo\nfoo" |  sed 'N;s/^/>/Mg' 
 >foo 
 >foo 
 $ 

Neste exemplo nos esforçamos por demonstrar a utilidade da bandeira (flag) "M" utilizando uma só expressão regular para juntar uma divisa no início de cada linha contida no espaço de trabalho depois do comando « N ».

Os comandos básicos 2


y
Transposição de caracteres
(intervalo de endereço autorizado)
  • O comando "y" permite converter qualquer caractere numerado na cadeia caractere fonte pelo seu homólogo, no lugar e espaço, se encontrando na cadeia caractere-destino.

O emprego mais comum para este comando é sem dúvidas a substituição dos caracteres acentuados tão valorizados na língua francesa. Eis um pequeno exemplo:
  
 sed ' 
 y/àâéèêëîïôöùûü/aaeeeeiioouuu/ 
 y/ÀÂÉÈÊËÎÏÔÖÙÛÜ/AAEEEEIIOOUUU/ 
 ' arquivo.txt 

a\
text
Ajout
(um endereço autorizado)
  • Adicione o texto "text" depois da linha colocada em correspondência pelo número de linha, motivo, expressão regular, e antes da leitura da linha seguinte. "text" corresponde a somente uma linha do texto, que pode, no entanto, conter saltos de linhas parecidas pelo "\" (backslash).

 sed '/Linha n° 5/ a\ 
 Bom dia 
 ' fich.txt 

i\
text
Inserção
(um endereço autorizado)
  • Insere o texto "text" antes da linha colocada em correspondência pelo seu numéro de linha, motivo ou expressão regular. "text" corresponde a uma só linha, que pode, no tentanto, conter saltos de linhas precedidas por "\" (backslash).

 sed '/Linha n° 4/ i\ 
 Bom dia 
 ' fich.txt 

c\
texto
Troca
(intervalo de endereço autorizado)
  • Troca da linha colocada em correspondência pelo número da linha, motivo ou expressão regular par "text". "text" corresponde a uma só linha, que pode, no entanto, conter saltos de linhas precedidas por "\" (backslash).

 sed '/Linha n° 2/,/Linha n° 6/ c\ 
 Anulado\ 
 Em razão \ 
 de trabalhos 
 ' fich.txt 


r arquivo read
Leitura
(um endereço autorizado)
  • Lê o conteúdo de "arquivo" no espaço de trabalho após o endereço especificado. Deve haver apenas um espaço entre o comando e o nome do arquivo. Tudo aquilo que segue depois do espaço até o final da linha é considerado o nome de arquivo . Assim, qualquer espaço ( incluindo tabulação </ ital>) será considerada como parte do nome. Se nenhum arquivo existir, nenhum aviso será emitido na saída padrão ou qualquer outro lugar. Se o arquivo não está no mesmo diretório onde o comando é iniciado, não se esqueça de especificar o caminho completo para o arquivo.


Você pode servir-se, por exemplo, para adicionar uma assinatura abaixo de uma série de arquivos. Para ilustrar estas idéias, nós iremos adicionar o conteúdo do arquivo « assinatura.txt » no final de todos os arquivos correspondentes ao motivo "fich*.txt" (<ital>observe o exemplo que segue e note o emprogo do switch "-s". Divirta-se a tirá-lo e note a diferença de afixagem
) :
 sed -s '$ assinatura.txt' fich*.txt 


w arquivo write
Exrever
(um endereço autorizado)
  • escreve a linha a ser processada no arquivo especificado após o comando "w ". Todos os comandos como o "r" ( ler</ ital>), só deve haver um espaço entre o comando e o nome do arquivo. Tudo o que segue este espaço até o final da linha é considerado como o nome do arquivo. Assim, qualquer espaço (<ital> incluindo a tabulação</ ital>) será considerada como parte do nome. Se um arquivo com o mesmo nome já existir, ele será substituído sem aviso ou confirmação, e isto em cada que cada chamada do script. No entanto, se múltiplas instruções do comando "w" são chamados para escrever no mesmo arquivo partir de um script, cada entrada (escritura) é adicionada ao final do arquivo.
  • Escreve a linha em tratamento no arquivo especificado no continuidade do comando "w". Como o comando "r" (<ital>leitura), não deve ter mais do que um espaço entre o comando e o nome do arquivo. Tudo o que segue este espaço até o final da linha é considerado como o nome do arquivo. Assim, qualquer espaço ( incluindo a tabulação</ ital>) será considerada como parte do nome. Se um arquivo com o mesmo nome já existir, ele será substituído sem aviso ou confirmação, e isto em cada que cada chamada do script. No entanto, se múltiplas instruções do comando "w" são chamados para escrever no mesmo arquivo partir de um script, cada entrada (escritura) é adicionada ao final do arquivo.


Se o arquivo não existir ele será criado, mesmo se o tratamento for nulo na saída (nenhuma escritura enviada.
Eis um pequeno cenário para colocar este comando em aplicação. A partir do arquivo "endereços.txt" agrupando nomes de distribuição associados à em código postal e sua cidade de referência, extrair o nome da distribuição e sua cidade associada e envie para um novo arquivo com o nome do departamento. Este script nomeado "foo.sed" será chamado da seguinte maneira :
sed -f foo.sed < endereços.txt 

Conteúdo do arquivo "foo.sed" :
 #n 

 /\b31/{ 
 s/[0-9][0-9]*// 
 w Haute-Garonne 
 } 
 /\b34/{ 
 s/[0-9][0-9]*// 
 w Hérault 
 } 
 /\b66/{ 
 s/[0-9][0-9]*// 
 w Pyrénées-Orientales 
 } 


=
  • Afixe o número da atual linha

 sed -n '/motivo/=' arquivo 

l [<ital>N
] --line-length=N
Césure
(intervalo de endereço autorizado)
  • Afixagem dos caracteres não imprimíveis - N permite especificar o comprimento do corte da linha desejada.

 sed -n l arquivo # afixagem caractere não imprimível  
 sed -n 'l 8' arquivo # idem mas com uma volta à linha cada 8 caracteres  

Os comandos avançados


Além dos comandos que nós acabamos de analisar, Sed possui outros comandos, certo, pouco utilizados, pois menos conhecidos e para alguns bastante difíceis de assimilar e a aplicar, mas que lhe permitem poder completar certas tarefas sem ter de servir-se do simples status de ferramenta ou de simples filtro.

Os comandos precedentes utilizados principalmente pelo seguinte mecanismo: leitura de uma linha do arquivo de entrada no espaço de trabalho o qual é aplicado a cada comando do script seqüencialmente. Quando o fim do script é atingido, a linha é, então, enviada para a saída standard, o espaço de trabalho é apagado, uma nova linha é lida em entrada e o controle passa novamente para o início do script.
Com os comandos que seguem, nós vamos ver como interagir no desenrolar do script, modificar o fluxo de entrada sob certas condições, estocar as partes de linhas, testar condições, etc...
Estes comandos podem ser decompostos em três grupos :
  • Os comandos multi-linhas (N,D,P)
  • Os comandos utilizando a memória anexa (h,H,g,G,x)
  • Os comandos de testes fazendo chamada à etiquetas (:,b,t,T)

Os comandos multi-linhas


N Next
Seguinte
(intervalo de endereço autorizado)
  • O comando "N" posiciona o caractere « nova linha » (\n) no fim do conteúdo do espaço de trabalho e adiciona a seguinte do fluxo de entrada no espaço de trabalho. Se o fim do arquivo de entrada é atingido, sed termina sua execução sem proceder ao tratamento de um novo comando. O caractere "nova linha" incorporado no espaço de trabalho pode ser validada pela seqüência de esc "\n". No espaço de trabalho "multilinhas", os meta-caracteres "^" e "$" validadam respectivamente o início e o fim deste espaço de trabalho e não os inícios e fins precedentes ou seguintes do caractere nova linha incorporada.

O exemplo que segue procura uma linha que contém o motivo "C". Se esta é encontrada, ele adiciona a linha seguinte no espaço de trabalho e substitui o caractere fim de linha "\n" não um hífem contornado por um espaço de cada lado:
eco -e "A\nB\nC\nD\nE" | sed  '/C/{N;s/\n/ - /}' 


D Delete
Apagar
(intervalo de endereço autorizado)
  • O comando "D" apaga o conteúdo do espaço de trabalho até o 1° caractere que delimita uma nova linha (\n). Se ainda faltam dados no espaço de trabalho, um novo ciclo é lançado com este conteúdo (sem ler uma nova linha em entrada ), senão um novo ciclo é lançado com a linha seguinte.

Para ilustrar o emprego do comando « D », eu vou pegar um exemplo dado no excelente livro publicado por O'Reilly (sed & awk, Second Edition) e que resume muito bem o mecanismo deste comando referente ao comando "d".

O arquivo de referência (comando_D.txt) :
Esta linha é seguida de uma linha vazia 

Esta linha é seguida de 2 linhas vazias  


Esta  linha é seguida de 3 linhas vazias 



Esta linha é seguida de 4 linhas vazias 



Fim do arquivo

Por razões de layout inerente a este artigo, no arquivo aqui acima, tem somente 3 linhas vazias abaixo da linha "Esta linha é seguida de 4 linhas vazias". Pense em adicionar uma 4° linha no momento de seus ensaios antes de experimentar este exemplo.
O objetivo é o de agrupar as linhas vazias consecutivas em uma só. O comando "d" parece apropriado para esta tarefa. Vejamos um 1° script utilizando este comando:
sed ' 
/^$/{ 
N 
/^\n$/d 
}' comando_D.txt 

Para fazer isso, vamos utilizar um padrão que nos permite combinar uma Linha vazia "/^$/". Depois de uma linha vazia for encontrada, pedimos a carga da linha a seguir na área de trabalho com o comando "N". Depois da linha carregada, podemos verificar se o atual padrão na área de trabalho corresponde ao padrão "/ ^ \ n $ /" (linha um salto de linha em tudo e para todos </ ital>) e seé bem isto, devemos apagar(comando "d "). Mas agora, isso só funciona para o caso desta sintaxe ou se o número de linhas for for ímpar. Isso é explicado pelo fato de que o comando "d"apaga todo o conteúdo do espaço de trabalho.

Com efeito, uma vez que uma linha vazia encontra a linha seguinte é carregado (N), se esta linha está vazia, o espaço de trabalho é apagado (d) e um novo ciclo é iniciado com uma nova linha. Assim, se esta nova Linha (3) está vazia, e a próxima não , então o o comando de apagamento (d) não é aplicado e a linha vazia é afixada.

Porém, por outro lado, se nós substituímos o comando "d" pelo seu homologue "D" desta maneira:
sed ' 
/^$/{ 
N 
/^\n$/D 
}' comando_D.txt 


Nós obtemos o resultado desejado. De fato, o comando "D" apaga apenas a parte do espaço de trabalho compreendido antes do primeiro caractere "/ n" (salto em Linha), assim se é linhas vazias são encontrados no espaço de trabalho apenas a 1° ainha primeiro é apagada e o script reinicia com o conteúdo da área de trabalho (<ital> uma Linha vazio </ ital>), uma nova Linha é carregada, se não está vazia, as 2 Linhas contidas no espaço de trabalho são enviadas para a saída padrão, caso contrário, a primeira parte é apagada e o cenário repete-se ...
Por outras palavras, se duas linhas vazias se encontram no espaço de trabalho somente a primeira é apagada, se é uma linha vazia seguida de texto, elas são enviadas na saída standard.



P <ital>Print

Afixagem
(intervalo de endereço autorizado)
  • Como seu homologo em minúscula que afixa o conteúdo do espaço de trabalho, o comando « P » afixa o conteúdo do espaço de trabalho até o 1° caractere que delimita uma nova linha (\n). Quando o último comando so script é atingido, o conteúdo do espaço de trabalho é automaticamente afixada na saída standard (a menos que a opção "-n" ou "#n" tenha sido empregada ).

As memórias tampão (buffer)


O editor de fluxo sed dispõe de duas memórias tampão que permitem estocar as linhas em tratamento.

Estas memórias tampão são seguidamente referenciadas sob o nome de "pattern space" para a memória principal, que se poderia traduzir por « espaço modelo » ou também « espaço de trabalho »,e por "hold space" para a memória secundária, traduzível por « "espaço anexo".

O espaço de trabalho (pattern space) é o espaço memória onde são mantidos os dados (a ou as linha(s)) selecionadas durante sua duração de tratamento.
O espaço anexo (hold space) é o espaço memória onde os dados (a ou as linha(s)) podem ser estocadas temporariamente.

Os comandos permitem de andar entre estes dois espaços que 5.
Breve resumo:
  • h Copia o espaço de trabalho na memória anexa
  • H Adiciona o espaço de trabalho na memória anexa
  • g Copia o conteúdo da memória no espaço de trabalho
  • G Adiciona o conteúdo da memória anexa no espaço de trabalho
  • x Troca de conteúdo das 2 memórias


Afora o comando "x", os outros comandos caminham por assim dizer por pares e agem para cada binômio como direções (>, >>, <,<<) dos interpretadores de comandos nos shell como "bash" ou "ksh". Seu papel poderia se o de traduzir desta maneira :
  • h > Esmaga o conteúdo
  • H >> Adiciona ao conteúdo
  • g < Esmaga o conteúdo
  • G << Adiciona ao conteúdo


Eis uma definição mais sintética de cada comando que pode afetar o espaço de trabalho :

h hold pattern space
espaço do modelo anexo
(intervalo de endereço autorizado)
  • O comando h copia o conteúdo do atual motivo (pattern space) na memória secundária, esmagando o conteúdo precedentemente copiado se presente. O tampão fica igual.


H Hold pattern space
Espaço de modelo anexo
(intervalo de endereço autorizado)
  • O comando H adiciona o conteúdo do atual motivo (pattern space) ao conteúdo da memória secundária. Os antigos conteúdo são separados por uma nova linha materializada pelo caractere "\n". O atual tampão fica igual. Uma nova linha (\n) é adicionada ao espaço de trabalho mesmo se este é vazio.


g get contents
Copia o conteúdo
(intervalo de endereço autorizado)
  • O comando g copie o conteúdo da memória secundária para o atual motivo, esmagando este último.


G Get contents
Adiciona o conteúdo
(intervalo de endereço autorizado)
  • O comando G adiciona o conteúdo da memória secundária a atual motivo. O antigo conteúdo e o novo são separados por uma nova linha materializada pelo caractere "\n". mem


x eXchange
Troca
(intervalo de endereço autorizado)
  • O comando x troca o conteúdo de ambas as memórias buffers (</ ital> principal e Secundária . Você deve saber que a Memória Secundária inicia seu ciclo com uma Linha vazio. Se você aplicar o comando "x" à primeira linha de um arquivo, a linha é colocada na memoria anexa e é substituida pelo conteúdo da memória anexa, quer dizer pela linha vazia. Você também deve saber que, seguindo este princípio, a última linha de um arquivo é colocada na memória anexa, mas jamais é restiuida no espaço de trabalho e assim jamais sera afixada, a menos de fazer uma solicitação implicita.


Você encontrará no final destes documentos alguns exemplos comentados sobre o emprego das memórias tampão de « sed », e para começar um pequeno exemplo muito simples (sempre tirado da obra das Éditions O'Reilly), muito fácil de entender, mas que nos chama a atenção para em erro às vezes incompreensível que pode acontecer e nos fazer girar à volta de si mesmo.
Um erro que concerne a memória anexa. Quando nós vemos o conteúdo do espaço de trabalho, e que nós operamos diversos tratamentos restituem o conteúdo da memória anexa somente sob certas condições, pode acontecer que este conteúdo não seja restituído no espaço de trabalho e assim, jamais enviado para a saída standard...

Eis a demosntração.
Nós afixaremos a seguinte variável:
$ A="1\n2\n11\n22\n111\n222" 
$ eco -e "$A" 
1 
2 
11 
22 
111 
222


e pedir a "sed" de intervir nas linhas que comecem por "1" com aquelas que começam por "2".

Para tanto nós começaremos por validar as linhas que começam por "1", copiar o conteúdo na memória anexa com o comando "h",depois esvaziar o espaço de trabalho, é o papel do comando "d". Neste momento, o controle é reenviado ao início do script, onde uma nova linha é carregada (com um « 2 »), a 1° comparação (/1/) não é válida, mas a segunda (/2/) é verdadeira, então o conteúdo da memória anexa é adicionada ao espaço de trabalho, que contém então "2\n1$". Como nós chegamos no final do script, o conteúdo do espaço de trabalho é afixado e substituído pela entrada seguinte (11) e o script recomeça, e assim por diante...

Eis o script :
eco -e "$A" | sed ' 
/1/{  # se o  motivo está presente  
h  # o copiar na memória anexa 
d  # apagar o conteúdo da memória principal 
} 
/2/{  # se o motivo está presente 
G  # adicionar o conteúdo da memória anexa }'


E na afixagem final:
2 
1 
22 
11 
222 
111


Como nós vimos, tudo se passa muito bem. Mas como ficaria se nós deslizássemos um "333" ao invés do "22" ? Pois bem, justamente é o que nós veremos a seguir.
Antes de tudo, a fixagem da nova variável :
$ A="1\n2\n11\n33\n111\n222" 
$ eco -e "$A" 
1 
2 
11 
33 
111 
222


E sua passagem no pente fino por "sed" :
$ eco -e "$A" | sed '/1/{h;d};/2/{G}' 
2 
1 
33 
222 
111


Como nós podemos notar, a afixagem do "11" passou desapercebida ! Por que? Porque, como foi dito no início do exemplo, o conteúdo da memória anexa não é restituída no espaço de trabalho a não ser que seja encontrado um motivo que contenha "2. Em caso contrário, o script continua seu caminho, dizendo de outra forma, ele afixa a seguinte linha (111), linha que satisfaz a condição do 1° motivo i (/1/) e assim envia seu conteúdo no espaço de trabalho, esmagando os dados presentes (11).

Então, cuidado na elaboração de certos scripts de restituir o conteúdo da memória anexa.

Etiquetas


As etiquetas permitem saltar até um lugar preciso, no interior do script. Sed possui três comandos previstos para isto. Um comando incondicional "b" como "branchement" (conexão)e dois comandos condicionais "t" et "T" como "[tT]est".

A sintaxe para designar uma etiqueta se limita a colocar no início da linha (<ital>por un script
) dois pontos seguidos de uma letra (ou suite de letras para formar uma palavra, esta última sendo recomendada para uma melhor legibilidade do código ).

:Etiqueta


Esta etiqueta será então chamada no script com a ajuda dos comandos "b", "t" ou "T".Simplesmente fazendo seu nome pelo comando desejado :
b etiqueta 
t etiqueta 
T etiqueta

Conexão incondicional


b branch
(intervalo de endereço autorizado)
  • O comando b permite transferir incondicionalmente a execução do script no lugar indicado pela etiqueta fornecida no argumento. Se, nenhum argumento for fornecido, o comando reenvia para o fim do script. O comando em andamento é então afixado, a não ser se a opção "-n" estava ativa e o script retoma sua execução com a próxima linha de fluxo de entrada.

Exemplo de conexão incondicional

Conexão condicional


t test
(intervalo de endereço autorizado)
  • O comando t permite transferir condicionalmente a execução do script no lugar indicado pela etiqueta fornecida em argumento se um comando de substituição conseguiu na linha em tratamento ou na última conexão condicional. Se nenhum argumento for fornecido, o comando reenvia ao fim do script.

Exemplo de conexão condicional 1

T test
(intervalo de endereço autorizado)
  • O comando T permite transferir condicionalmente a execução do script no lugar indicado pela etiqueta em argumento se um comando de substituição não tive sido validado na linha em tratamento ou na última conexão condicional. Se nenhum argumento for fornecido, o comando reenvia ao fim do script.

Exemplo de conexão condicioal 2

SED - The Stream EDitor - Part II


Suite Part II => SED - The Stream EDitor - Part II
Tradução feita por Ana Spadari

Veja também :
Este documento, intitulado « Sed - Introdução ao SED - Part I »a partir de CCM (br.ccm.net) está disponibilizado sob a licença Creative Commons. Você pode copiar, modificar cópias desta página, nas condições estipuladas pela licença, como esta nota aparece claramente.