Postagem em destaque

Criando bot do Telegram em Shell script com ShellBot

Imprimindo intervalo de linhas de um arquivo.

Em ambientes Unix-like a manipulação de arquivos em modo texto é uma prática comum entre Administradores de sistema; sejam eles arquivos de log, configuração ou até mesmo um simples texto unicode. 

O Linux dispõe de um acervo de comandos para tal finalidade, que na maioria dos casos basta apenas a execução solitária seguido do arquivo para obtermos o conteúdo; mas nem sempre são só flores, há momentos que pegamos arquivos indigestos, com dezenas de milhares de linhas ou mais e que devemos tratá-las individualmente para conseguir o que queremos.

Vou mostrar algumas dicas úteis que podem lhe ajudar nesses momentos. Antes de começar precisamos de um arquivo onde iremos testar nossas linhas de comando.

Considere o arquivo cores.txt com o seguinte conteúdo.

Cinza
Vermelho
Azul
Ciano
Verde
Amarela
Magenta
Violeta
Alaranjado
Branco
Preto
Castanho

O comando que irei utilizar para listar o conteúdo do arquivo no decorrer dos exemplos será o cat e como estamos trabalhando com linhas, vou acrescentar o parâmetro '-n' para enumera-las; assim ficará tranquilo de entender.

Testando...
$ cat -n cores.txt
     1    Cinza
     2    Vermelho
     3    Azul
     4    Ciano
     5    Verde
     6    Amarela
     7    Magenta
     8    Violeta
     9    Alaranjado
    10    Branco
    11    Preto
    12    Castanho

1. Imprimindo as últimas linhas (tail)


Em alguns casos, manipulamos arquivos dos quais não temos conhecimento da quantidade de linhas que ele possui e consequentemente seria complicado especificar quais as últimas N linhas se não sabemos qual é a última linha; claro que esse problema poderia ser contornado com o uso de um segundo comando, que não é o caso.

Para essa finalidade utilizarei o comando tail com o seguinte parâmetro:

Sintaxe: tail -n [+]N

ParâmetroDescrição
-n Imprime as últimas N linhas (Padrão: 10 últimas linhas)
NQuantidade de linhas.
+A partir de

1.1 Imprimindo as últimas 5 linhas.


$ cat -n cores.txt  | tail -n 5
     8    Violeta
     9    Alaranjado
    10    Branco
    11    Preto
    12    Castanho

Retornou as linhas de 8 à 12 (última), se contarmos teremos um total de 5 linhas; exatamente o que foi especificado.

O uso do sinal de '+' (adição) antes do valor 'N', muda o comportamento do comando fazendo com que ele deixe de imprimir as últimas 'N' linhas e passe a imprimir a partir da linha 'N' em diante.

1.2 Imprimindo da linha 5 em diante.


$ cat -n cores.txt  | tail -n +5
     5    Verde
     6    Amarela
     7    Magenta
     8    Violeta
     9    Alaranjado
    10    Branco
    11    Preto
    12    Castanho

Retornou todas as linhas posteriores a linha 5.

2. Imprimindo as primeiras linhas. (head)


Esse comando é o oposto ao tail; ele imprime as primeiras 'N' linhas de um arquivo.

Para essa finalidade vou utilizar o parâmetro:

Sintaxe: head -n [-]N

ParâmetroDescrição
-nImprime as primeiras N linhas. (Padrão: 10 primeiras linhas)
NQuantidade de linhas.
-Exceto as últimas 'N' linhas.


2.1 Imprimindo as primeiras 5 linhas.


$ cat -n cores.txt | head -n 5
     1    Cinza
     2    Vermelho
     3    Azul
     4    Ciano
     5    Verde


2.2 Imprimindo todas as linhas exceto as 2 últimas.

Usando o sinal de '-' (subtração) antes do valor, faz com que o comando imprima tudo exceto as últimas 'N' linhas.

$ cat -n cores.txt | head -n -2
     1    Cinza
     2    Vermelho
     3    Azul
     4    Ciano
     5    Verde
     6    Amarela
     7    Magenta
     8    Violeta
     9    Alaranjado
    10    Branco

Retornou as 10 primeiras linhas exceto as linhas 11 e 12 que são as duas últimas.

3. Imprimindo intervalos de linhas (tail + head)


Além de imprimir linhas iniciais e finais de um arquivo, também podemos extrair um determinado intervalo; para isso precisamos combinar os comandos tail e head.

O conceito é:

O primeiro comando lê a entrada padrão extraindo um determinado número de linhas que por sua vez é redirecionado para o segundo que extrai um novo intervalo.

Imagine que você precise imprimir somente as linhas 7,8 e 9, porém essas linhas não são as últimas do arquivo e utilizando apenas o comando tail não seria suficiente; para ter êxito preciso utilizar os comandos tail e head em conjunto.

3.1 Imprimindo as linhas 7,8 e 9.


Primeiro tenho que encontrar meu ponto de partida que é a linha inicial do meu intervalo. Considerando que preciso das linhas 7,8 e 9, posso afirmar que a linha inicial é a 7, então o que preciso é imprimir dessa linha em diante.

$ cat -n cores.txt | tail -n +7
     7    Magenta
     8    Violeta
     9    Alaranjado
    10    Branco
    11    Preto
    12    Castanho

Foi retornado todos os elementos a partir da linha 7, criando uma nova lista que agora a nossa antiga linha 7 passa a ser a linha 1.

Para finalizar usarei o comando head para imprimir as três primeiras linhas da lista, que são 7,8 e 9.

$ cat -n cores.txt | tail -n +7 | head -n 3
     7    Magenta
     8    Violeta
     9    Alaranjado

Ou podemos utilizar o comando head para imprimir as primeiras 9 linhas do arquivo e redirecionar para o tail que extrai as 3 últimas.

$ cat -n cores.txt | head -n 9 | tail -n 3
     7    Magenta
     8    Violeta
     9    Alaranjado

4. Imprimindo linha ou linhas especificas (sed)


Agora chegamos no todo poderoso sed, onde nossas possibilidades são ilimitadas. Sinceramente precisaria de uma vida inteira para falar sobre ele e ainda correria o risco de morrer antes. 💀😇😆 Dentro do contexto abordado vou conseguir sem problemas.

Sintaxe: sed -n 'N p'

ParâmetroDescrição
-nSuprime a impressão do buffer padrão
NNúmero da linha
pImprime espaço padrão

Neste caso em especifico o uso do parâmetro -n é necessário para omitir o buffer padrão e que somente as linhas especificadas sejam impressas pela parâmetro p, evitando assim linhas duplicadas.

4.1 Imprimindo linha 3.


$ cat -n cores.txt | sed -n '3 p'
     3    Azul

Nota: O caractere p (TAG), pode ser inserido junto ao número da linha. Exemplo: '3p'

Porém, para facilitar a leitura vou mantê-los separados.

4.2 Imprimindo linhas 3, 5 e 9


Para especificar múltiplas linhas é preciso separá-las usando ';' (ponto e vírgula)
e inserir o caractere p (TAG) ao final de cada número.

$ cat -n cores.txt | sed -n '3 p;5 p;9 p'
     3    Azul
     5    Verde
     9    Alaranjado

4.3 Imprimindo a última linha.


Na maioria da vezes não sabemos qual é a última linha de um arquivo, por isso o sed conta com o meta caractere '$' (cifrão), que representa o final do arquivo.

$ cat -n cores.txt | sed -n '$ p'
    12    Castanho

5. Imprimindo intervalos de linhas (sed)


Para especificar um intervalo, os endereços devem ser separados por uma ',' (vírgula).

Sintaxe: sed -n 'N,M p'

ParâmetroDescrição
NEndereço inicial
MEndereço final

5.1 Imprimindo da linha 3 até a 10.


$ cat -n cores.txt | sed -n '3,10 p'
     3    Azul
     4    Ciano
     5    Verde
     6    Amarela
     7    Magenta
     8    Violeta
     9    Alaranjado
    10    Branco

5.2 Imprimindo da linha 4 até 9 e a linha 11. 


Também podemos mesclar regras, separando-as com ';' (ponto e vírgula).

$ cat -n cores.txt | sed -n '4,9 p;11 p'
     4    Ciano
     5    Verde
     6    Amarela
     7    Magenta
     8    Violeta
     9    Alaranjado
    11    Preto


6. Imprimindo uma determinada quantidade de linhas (sed)


Sintaxe: sed -n 'N,+M p'

ParâmetroDescrição
NEndereço inicial
+MCorresponde à M linhas após 'N'.

O sinal de '+' (adição) faz com que o comando imprima as 'M' linhas a partir do endereço inicial 'N'. O uso do endereço 'N' é obrigatório.

6.1 Imprimindo a linha 3 e as 5 linhas posteriores.


$ cat -n cores.txt | sed -n '3,+5 p'
     3    Azul
     4    Ciano
     5    Verde
     6    Amarela
     7    Magenta
     8    Violeta

7. Imprimindo linhas intercaladas (sed)


Sintaxe: sed -n 'N~M p'

ParâmetroDescrição
NEndereço inicial
~MNúmero de saltos

O sinal de '~' (circunflexo) faz com que o comando realize 'M' saltos a partir do endereço inicial 'N', criando um fluxo intercalado.

7.1 Imprimindo somente as linhas pares.


$ cat -n cores.txt | sed -n '2~2 p'
     2    Vermelho
     4    Ciano
     6    Amarela
     8    Violeta
    10    Branco
    12    Castanho

7.2 Imprimindo somente as linhas ímpares.


$ cat -n cores.txt | sed -n '1~2 p'
     1    Cinza
     3    Azul
     5    Verde
     7    Magenta
     9    Alaranjado
    11    Preto

8. Mesclando regras (sed)

Como mencionei anteriormente podemos criar inúmeras regras de tratamento para uma ou mais linhas especificas.

8.1 Imprimindo da linha 1 à 5 e da linha 6 em diante somente as pares.


$ cat -n cores.txt | sed -n '1,5 p;6~2 p'
     1    Cinza
     2    Vermelho
     3    Azul
     4    Ciano
     5    Verde
     6    Amarela
     8    Violeta
    10    Branco
    12    Castanho

8.2 Imprimindo duas vezes somente as linhas pares.


$ cat -n cores.txt | sed -n '1,$ p;2~2 p'
     1    Cinza
     2    Vermelho
     2    Vermelho
     3    Azul
     4    Ciano
     4    Ciano
     5    Verde
     6    Amarela
     6    Amarela
     7    Magenta
     8    Violeta
     8    Violeta
     9    Alaranjado
    10    Branco
    10    Branco
    11    Preto
    12    Castanho
    12    Castanho

Provavelmente você deve estar se perguntando. Ele não tinha dito que o parâmetro -n omite o buffer padrão para evitar linhas duplicadas ? Porque temos então linhas duplicadas ?

Sim, mas note que temos duas regras de impressão para o mesmo grupo de linhas.

Regras:
  1. (1,$ p) Imprime todas as linhas do arquivo.
  2. (2~2 p) Imprime as linhas pares.
O caractere p (TAG) representa a ação de imprimir a linha de em uma determinada regra; por essa razão as linhas que se enquadram em ambas as regras, são impressas duas vezes.

8.3 Imprimindo a linha 4 mais 4 linhas posteriores e a última linha.


$ cat -n cores.txt | sed -n '4,+4 p;$ p;'
     4    Ciano
     5    Verde
     6    Amarela
     7    Magenta
     8    Violeta
    12    Castanho

Como eu disse, as possibilidades são ilimitadas; tudo irá depender da sua imaginação para resolução do problema. Particularmente eu prefiro o sed quando o assunto é manipulação de arquivo/texto; não conheço outra ferramenta tão poderosa capaz de oferecer ao usuário a capacidade de programar e criar regras complexas.

Abordei algumas alternativas para manipulação de linhas de um arquivo, espero que vocês pratiquem bastante e em breve estejam desenvolvendo regras cabulosas.

Comentários

Postar um comentário

Contato

Nome

E-mail *

Mensagem *