Discussion:
[shell-script] Dúvida sobre Pattern Space do Sed
andrelucio.fc@yahoo.com [shell-script]
2016-10-17 18:34:00 UTC
Permalink
Olá, senhores.

Estou com uma dúvida relacionada ao comando 'N' do SED, alguém poderia me explicar o funcionamento do mesmo juntamente com um exemplo prático.


Eu sei que pode ser uma pergunta besta, mas estudei e estudei e não conseguir entender.


Desde já agradeço pela ajuda.
'Julio C. Neves' julio.neves@gmail.com [shell-script]
2016-10-17 19:47:19 UTC
Permalink
Um pedaço do meu livro:
Comandos que interagem com os buffers

Existem oito comandos - cuja funções estão sintetizadas na tabela a seguir
- para o sed interagir com esses dois *buffers*:

*Comandos*

*Função*

n N

Lê/adiciona a próxima linha ao *Pattern Space*.

h H

Copia/adiciona *Pattern Space* ao *Hold Space.*

g G

Copia/adiciona *Hold Space* ao *Pattern Space*.

p P

Imprime todas/1ª linha do *P**attern **S**pace*

d...D

Deleta todas/1ª linha do *P**attern **S**pace*

x

Intercambia o conteúdo dos dois *buffers*.

Na tabela que acabamos de ver, "copia" significa colocar um conteúdo no
*buffer*, destruindo o que já havia e "adiciona", significa somar o dado ao
que já existia no *buffer,* separando o conteúdo antigo do recente por um
<ENTER> (\n).

Ainda sobre essa tabela, os comandos p e d, são os mesmos que já vimos, que
servem para listar e deletar, respectivamente, o conteúdo do *Pattern*
*Space.*

Como tive muita dificuldade para entender isso, vou explicar bem devagar:

O comando n imprime todo o conteúdo do *Pattern* *Space* (a não ser que a
opção -n do sed esteja ativa), esvazia totalmente o *Pattern* *Space* e lê
o próximo registro.

O comando N não lista nem esvazia o *Pattern* *Space*, ele manda ler mais
uma linha e a coloca por baixo do que já existia no *Pattern* *Space*,
separando-a do que lá estava por um caractere de *line* *feed* (<ENTER>).

O comando p, é nosso velho conhecido e ele lista todo o conteúdo do
*Pattern* *Space*., já o comando P, lista somente até o primeiro *line*
*feed* (<ENTER>), isto é, lista somente a primeira linha do *Pattern*
*Space*. Nenhum dos dois altera o conteúdo do *Pattern* *Space*.

Vamos ver exemplos:

*$ seq 6 | sed -n 'N;P' # P MAIÚSCULO*

1

3

5

*$ seq 6 | sed -n 'N;p' # p minúsculo*

1

2

3

4

5

6

No primeiro exemplo listei somente os ímpares, porque enquanto o N enfiava
a linha par por baixo da ímpar no *buffer*, o P imprimia somente a
primeira. No segundo o p imprimia todo o conteúdo, então listou toda a
entrada.

*$ seq 6 | sed -n 'n;P' # P MAIÚSCULO*

2

4

6

*$ seq 6 | sed -n 'n;p' # p minúsculo*

2

4

6

Nesse caso a saída dos 2 exemplos é idêntica, porque o comando n é
destrutivo. ele apagou o *buffer* (que no início tinha o número 1) e jogou
outro por cima (no caso o 2). Como tinha uma única linha no *Pattern*
*Space*, tanto faz usar o p ou o P.

O comando d apaga o conteúdo do *Pattern* *Space*, lê a próxima linha e sai
do comando, voltando para o sed.

O comando D remove somente a primeira linha do *Pattern* *Space*, e volta
para o primeiro comando do sed.

Para eliminar a linha que tem a cadeia 3:

*$ seq 6 | sed '/3/{d;n}'*

1

2

4

5

6

Ou seja, quando encontrou a cadeia 3, o comando d mandou esvaziar o
*Pattern* *Space* mandando seu conteúdo (o 3) pro brejo e o n leu o próximo
registro.

Para deletar 3 linhas a partir da linha 2, podemos fazer:

*$ seq 6 | sed '2 { # **Posiciona na linha 2*

*> N # **Lê a 3 para o **Pattern* *Space*

*> N # **Lê a 4 para o **Pattern* *Space*

*> d # **Limpa o Pattern Space*

*> }'*

1

5

6

Os comentários laterais já explicaram esse exemplo.

Vamos numerar as linhas de frutas:

*$ cat frutas*

abacate

maçã

morango

pera

tangerina

uva

*$ sed '=' frutas *

1

abacate

2

maçã

3

morango

4

pera

5

tangerina

6

uva

Agora vamos botar o número junto à linha, separados por um <TAB>.

*$ sed = frutas | sed 'N;s/\n/\t/'*

1 abacate

2 maçã

3 morango

4 pera

5 tangerina

6 uva

Ou seja, o N trouxe outra linha para o *Space* *Buffer* e o comando s (
*substitute*) trocou o <ENTER> (\n) pelo <TAB> (\t).

Abcs,
Julio
*@juliobash*

*Próximos cursos de Shell*
*Cidade Local Período*
*​*
*São Paulo 4Linux
<https://www.4linux.com.br/curso/programacao-em-shell-script> 05-09/12*
Dou treinamento de *Shell* em qualquer cidade.
Post by ***@yahoo.com [shell-script]
Olá, senhores.
Estou com uma dúvida relacionada ao comando 'N' do SED, alguém poderia me
explicar o funcionamento do mesmo juntamente com um exemplo prático.
Eu sei que pode ser uma pergunta besta, mas estudei e estudei e não conseguir entender.
Desde já agradeço pela ajuda.
Janduy Euclides janduyeuclides@googlemail.com [shell-script]
2016-10-17 21:57:13 UTC
Permalink
O livro do Júlio é fantástico, não sou nenhum craque em Shell como a
maioria dos integrantes do grupo. Mas o livro é muito bom!

Parabéns Júlio!

Em 17 de out de 2016 18:13, "'Julio C. Neves' ***@gmail.com
[shell-script]" <shell-***@yahoogrupos.com.br> escreveu:



Um pedaço do meu livro:
Comandos que interagem com os buffers

Existem oito comandos - cuja funções estão sintetizadas na tabela a seguir
- para o sed interagir com esses dois *buffers*:

*Comandos*

*Função*

n N

Lê/adiciona a próxima linha ao *Pattern Space*.

h H

Copia/adiciona *Pattern Space* ao *Hold Space.*

g G

Copia/adiciona *Hold Space* ao *Pattern Space*.

p P

Imprime todas/1ª linha do *P**attern **S**pace*

d...D

Deleta todas/1ª linha do *P**attern **S**pace*

x

Intercambia o conteúdo dos dois *buffers*.

Na tabela que acabamos de ver, "copia" significa colocar um conteúdo no
*buffer*, destruindo o que já havia e "adiciona", significa somar o dado ao
que já existia no *buffer,* separando o conteúdo antigo do recente por um
<ENTER> (\n).

Ainda sobre essa tabela, os comandos p e d, são os mesmos que já vimos, que
servem para listar e deletar, respectivamente, o conteúdo do *Pattern*
*Space.*

Como tive muita dificuldade para entender isso, vou explicar bem devagar:

O comando n imprime todo o conteúdo do *Pattern* *Space* (a não ser que a
opção -n do sed esteja ativa), esvazia totalmente o *Pattern* *Space* e lê
o próximo registro.

O comando N não lista nem esvazia o *Pattern* *Space*, ele manda ler mais
uma linha e a coloca por baixo do que já existia no *Pattern* *Space*,
separando-a do que lá estava por um caractere de *line* *feed* (<ENTER>).

O comando p, é nosso velho conhecido e ele lista todo o conteúdo do
*Pattern* *Space*., já o comando P, lista somente até o primeiro *line*
*feed* (<ENTER>), isto é, lista somente a primeira linha do *Pattern*
*Space*. Nenhum dos dois altera o conteúdo do *Pattern* *Space*.

Vamos ver exemplos:

*$ seq 6 | sed -n 'N;P' # P MAIÚSCULO*

1

3

5

*$ seq 6 | sed -n 'N;p' # p minúsculo*

1

2

3

4

5

6

No primeiro exemplo listei somente os ímpares, porque enquanto o N enfiava
a linha par por baixo da ímpar no *buffer*, o P imprimia somente a
primeira. No segundo o p imprimia todo o conteúdo, então listou toda a
entrada.

*$ seq 6 | sed -n 'n;P' # P MAIÚSCULO*

2

4

6

*$ seq 6 | sed -n 'n;p' # p minúsculo*

2

4

6

Nesse caso a saída dos 2 exemplos é idêntica, porque o comando n é
destrutivo. ele apagou o *buffer* (que no início tinha o número 1) e jogou
outro por cima (no caso o 2). Como tinha uma única linha no *Pattern*
*Space*, tanto faz usar o p ou o P.

O comando d apaga o conteúdo do *Pattern* *Space*, lê a próxima linha e sai
do comando, voltando para o sed.

O comando D remove somente a primeira linha do *Pattern* *Space*, e volta
para o primeiro comando do sed.

Para eliminar a linha que tem a cadeia 3:

*$ seq 6 | sed '/3/{d;n}'*

1

2

4

5

6

Ou seja, quando encontrou a cadeia 3, o comando d mandou esvaziar o
*Pattern* *Space* mandando seu conteúdo (o 3) pro brejo e o n leu o próximo
registro.

Para deletar 3 linhas a partir da linha 2, podemos fazer:

*$ seq 6 | sed '2 { # **Posiciona na linha 2*

*> N # **Lê a 3 para o **Pattern* *Space*

*> N # **Lê a 4 para o **Pattern* *Space*

*> d # **Limpa o Pattern Space*

*> }'*

1

5

6

Os comentários laterais já explicaram esse exemplo.

Vamos numerar as linhas de frutas:

*$ cat frutas*

abacate

maçã

morango

pera

tangerina

uva

*$ sed '=' frutas *

1

abacate

2

maçã

3

morango

4

pera

5

tangerina

6

uva

Agora vamos botar o número junto à linha, separados por um <TAB>.

*$ sed = frutas | sed 'N;s/\n/\t/'*

1 abacate

2 maçã

3 morango

4 pera

5 tangerina

6 uva

Ou seja, o N trouxe outra linha para o *Space* *Buffer* e o comando s (
*substitute*) trocou o <ENTER> (\n) pelo <TAB> (\t).

Abcs,
Julio
*@juliobash*

*Próximos cursos de Shell*
*Cidade Local Período*
*​*
*São Paulo 4Linux
<https://www.4linux.com.br/curso/programacao-em-shell-script> 05-09/12*
Dou treinamento de *Shell* em qualquer cidade.
Post by ***@yahoo.com [shell-script]
Olá, senhores.
Estou com uma dúvida relacionada ao comando 'N' do SED, alguém poderia me
explicar o funcionamento do mesmo juntamente com um exemplo prático.
Eu sei que pode ser uma pergunta besta, mas estudei e estudei e não conseguir entender.
Desde já agradeço pela ajuda.
andrelucio.fc@yahoo.com [shell-script]
2016-10-20 13:20:27 UTC
Permalink
Grande mestre Júlio,

Obrigado pela ajuda, com essa explicação deu para clarear um pouco as coisas.


Obs: Já encomendei o seu livro, resta agora esperar rs.

Loading...