Postagem em destaque

Renumerando itens de um arquivo.

Essa postagem é o resultado de uma ajuda que prestei a um membro do grupo shellbr no telegram, do qual faço parte. Como todo problema que se preze, vale a pena compartilhar a solução. Não utilizarei o arquivo original do usuário em nossa demonstração; para isso criei um arquivo chamado sistemas.txt que mantém o padrão de formatação do original.

Considere o conteúdo a seguir:

$ cat sistemas.txt
Slackware 0001
Windows 7 0002
Windows ME 0003
Debian 0004
Fedora 0005
Windows XP 0006
Manjaro 0007
Windows Server 2003 0008
Windows NT 0009
Arch 0010
Windows 98 0011
CentOS 0012
Ubuntu 0013
Windows Server 2008 0014
OpenSUSE 0015
Red Hat 0016
Elementary OS 0017
Windows 95 0018
Gentoo 0019
Windows 8 0020
Windows 10 0021
Satux 0022

Agora que temos uma visão do seu conteúdo, vou explicar o problema hipotético enfrentando pelo usuário.

O arquivo é constituído de uma lista de Sistemas operacionais, onde ao final de cada item havia um código de quatro dígitos que definia a sua posição no arquivo.

Diariamente ele recebe o arquivo de terceiros e precisa executar manualmente as seguintes tarefas:

  • Remover todas as linhas que continha a palavra Windows.
  • Renumerar os itens que sobravam

Apesar do arquivo conter algumas dezenas de linhas, era um processo cansativo e sujeito a falha humana. O usuário imaginou que criando um script poderia automatizar o processo e agilizar sua vida. (pensou certo).

O método que escolhi para a resolução do problema foi montar uma expressão regular com sed. Vou iniciar dividindo-a em etapas para melhor entendimento.

1ª Etapa


Remover as linhas com a palavra Windows.

$ cat sistemas.txt | sed '/Windows/d'
Slackware 0001
Debian 0004
Fedora 0005
Manjaro 0007
Arch 0010
CentOS 0012
Ubuntu 0013
OpenSUSE 0015
Red Hat 0016
Elementary OS 0017
Gentoo 0019
Satux 0022

Remover as linhas foi uma tarefa fácil.

2ª Etapa


Após a remoção das linhas, é necessário enumerar a nova lista.

$ cat sistemas.txt | sed '/Windows/d' | sed =
1
Slackware 0001
2
Debian 0004
3
Fedora 0005
4
Manjaro 0007
5
Arch 0010
6
CentOS 0012
7
Ubuntu 0013
8
OpenSUSE 0015
9
Red Hat 0016
10
Elementary OS 0017
11
Gentoo 0019
12
Satux 0022

Retornou a lista inserindo o número da linha antes de cada item.

3ª Etapa


Apesar dos novos números estarem corretos, precisamos converte-los para o padrão de quatro dígitos; para isso criei um loop, que enquanto o número inicial de cada linha for inferior a três dígitos, insira um zero a esquerda.
Exemplo: 1, 01, 001, 0001.

$ cat sistemas.txt | sed '/Windows/d' |  sed '=' | sed -r ':a;s/^[0-9]{1,3}$/0&/;ta'
0001
Slackware 0001
0002
Debian 0004
0003
Fedora 0005
0004
Manjaro 0007
0005
Arch 0010
0006
CentOS 0012
0007
Ubuntu 0013
0008
OpenSUSE 0015
0009
Red Hat 0016
0010
Elementary OS 0017
0011
Gentoo 0019
0012
Satux 0022

4ª Etapa


Anexar a próxima linha com a linha atual e remover o antigo código do final de cada linha.

$ cat sistemas.txt | sed '/Windows/d' |   sed '=' | sed -r ':a;s/^[0-9]{1,3}$/0&/;ta;N;s/\n/ /;s/[0-9]+$//'
0001 Slackware
0002 Debian
0003 Fedora
0004 Manjaro
0005 Arch
0006 CentOS
0007 Ubuntu
0008 OpenSUSE
0009 Red Hat
0010 Elementary OS
0011 Gentoo
0012 Satux

Ultima etapa


Estamos quase lá, a única coisa que precisamos é trocar a ordem do itens, passando o código para o final de cada linha e remover os espaços iniciais.

$ cat sistemas.txt | sed '/Windows/d' |  sed '=' | sed -r ':a;s/^[0-9]{1,3}$/0&/;ta;N;s/\n/ /;s/[0-9]+$//;s/^([0-9]+)(.*)$/\2\1/;s/^\s*//'
Slackware 0001
Debian 0002
Fedora 0003
Manjaro 0004
Arch 0005
CentOS 0006
Ubuntu 0007
OpenSUSE 0008
Red Hat 0009
Elementary OS 0010
Gentoo 0011
Satux 0012

Opa !!! Conseguimos excluir os itens indesejados e renumerar a nova lista.

Eu sei o que passou pela sua cabeça. "Que bizarro !!!, fazer essa expressão regular do cão. Não seria melhor fazer um script, como foi cogitado de inicio ?!!"

Em alguns casos sim, mas depois que você pega o gosto pelo sed a parada vira um vício.😅😅😂😂

Mas..., não esqueci de montar a solução via SCRIPT !!!!!

Script: xrenumerar.sh


#!/bin/bash

#-------------------------------------------------
# Data:       5 de Dezembro de 2016
# Criado por: Julano Santos [SHAMAN]
# Script:     xrenumerar.sh
# Descrição:  Remove os itens indesejados e renumera
#             os itens da nova lista.
# Página:     http://www.shellscriptx.blogspot.com.br
# Github:     https://github.com/shellscriptx
#-------------------------------------------------

# Caminho do arquivo que contém os itens que deseja renumerar.
ARQ=./sistemas.txt

# indice
NUM=0

# Lê o arquivo e armazena em LINHA
while read LINHA
do
    # Incrementa o indice +1
    ((NUM++))

    # Insere os zeros a esquerda do valor de NUM e armazena em COD.
    # Se o código possuir mais que 4 dígitos, basta alterar o valor
    # no formato do printf.
    COD=$(printf '%04d' $NUM)

    # Substitui o código do final da linha pelo novo.
    echo $LINHA | sed -r "s/\b[0-9]+$/$COD/"

    # Descomente se o código for no inicio da linha
    # echo $LINHA | sed -r "s/^[0-9]+\b/$COD/"


# Lê o arquivo ignorando as linhas que contém a palavra windows.
# Insira aqui as palavras que deseja excluir, separando-as por | (PIPE)
# (palavra1|palavra2|...)
done < <(grep -v 'Windows' "$ARQ")

exit 0
#FIM

Testando...

Problema resolvido !!! Agora cabe ao usuário redirecionar a saída do script ou sed para criação de um novo arquivo.

$ cat sistemas.txt | sed '/Windows/d' |  sed '=' | sed -r ':a;s/^[0-9]{1,3}$/0&/;ta;N;s/\n/ /;s/[0-9]+$//;s/^([0-9]+)(.*)$/\2\1/;s/^\s*//' > novo_arquivo.txt

ou

$ ./xrenumerar.sh > novo_arquivo.txt


Esse tipo de postagem é interessante quando baseado em problemas reais, onde a dúvida de um usuário pode ser a dúvida ou problema de muitos.

Comentários

Contato

Nome

E-mail *

Mensagem *