Existe alguma forma de ordenar um arquivo texto por colunas da ESQ. para a DIR. ? [RESOLVIDO]

1. Existe alguma forma de ordenar um arquivo texto por colunas da ESQ. para a DIR. ? [RESOLVIDO]

Mestre Kame
mlgrassi

(usa Debian)

Enviado em 09/07/2017 - 14:12h

Prezados,

Supondo que eu tenha um arquivo texto desorganizado, contendo várias linhas e várias colunas e utilizando como separador o ponto e vírgula. O exemplo a seguir ilustra uma amostra para fins explicativos:

Telefone;Endereço;Nome do Cliente;ID;Bairro;Estado;Cidade;Número
(21)3234-1234;Rua João Paulo Segundo;Rogério da Silva;04321;Tijuca;RJ;Rio de Janeiro;444
(48)2431-5465;Av. Beira Mar;Francisco Xavier;05354;Jurerê;SC;Florianópolis;43

Sabe-se que existe o comando sort que por default ordena por linha. Pode-se até, combinando suas opções, gerar uma saída mais organizada, informando um separador e ordenar por coluna. Só que pelo que eu sei, somente dá para se ter uma ordenação SEMPRE e somente de cima para baixo.

O meu objetivo é ordenar de forma a organizar o arquivo por colunas da ESQUERDA para a DIREITA, tendo a PRIMEIRA linha como referência, pois é a linha que contém o nome de cada coluna. Logo gostaria de saber quais os comandos que podem ser utilizados em shell, para que o exemplo acima fique da seguinte forma ordenado por coluna alfabeticamente tendo como referência a primeira linha:

Bairro;Cidade;Cliente;Endereço;Estado;ID;Número;Telefone
Tijuca;Rio de Janeiro;Rogério da Silva;Rua João Paulo Segundo;RJ;04321;444;(21)3234-1234
Jurerê;Florianópolis;Francisco Xavier;Av. Beira Mar;SC;05354;43;(48)2431-5465

Alguma sugestão?


  


2. Re: Existe alguma forma de ordenar um arquivo texto por colunas da ESQ. para a DIR. ? [RESOLVIDO]

Mauriciodez
Mauriciodez

(usa Debian)

Enviado em 09/07/2017 - 15:53h

Pode ser assim ??
awk -F ";" '{print $5,$7,$3,$2,$6,$4,$8,$1;}' arquivo.txt 






------------------------------------------| Linux User #621728 |-----------------------------------------
" Nem sempre é amigo aquele que te tira do buraco !!! ( Saddam Hussein )"
------------------------------------------| Linux User #621728 |-----------------------------------------



3. Re: Existe alguma forma de ordenar um arquivo texto por colunas da ESQ. para a DIR. ? [RESOLVIDO]

Mestre Kame
mlgrassi

(usa Debian)

Enviado em 09/07/2017 - 16:32h

Na realidade não amigo, pois em vosso exemplo o awk é estático.
Este método não resolve meu problema pois os arquivos que eu recebo para ordenar são aleatórios, de modo que nem sempre as colunas chegam nessa ordem alfabética.

Teria de ser algum comando ou conjunto de comandos que analise cada palavra da primeira linha, e as ordene em ordem crescente, fazendo uma permuta completa da coluna para a posição alfabética correta, fazendo isso dinamicamente pois cada arquivo pode vir diferente.


4. Re: Existe alguma forma de ordenar um arquivo texto por colunas da ESQ. para a DIR. ? [RESOLVIDO]

Mauriciodez
Mauriciodez

(usa Debian)

Enviado em 09/07/2017 - 17:18h

mlgrassi escreveu:

Na realidade não amigo, pois em vosso exemplo o awk é estático.
Este método não resolve meu problema pois os arquivos que eu recebo para ordenar são aleatórios, de modo que nem sempre as colunas chegam nessa ordem alfabética.

Teria de ser algum comando ou conjunto de comandos que analise cada palavra da primeira linha, e as ordene em ordem crescente, fazendo uma permuta completa da coluna para a posição alfabética correta, fazendo isso dinamicamente pois cada arquivo pode vir diferente.


a tá ... entendi agora ... velho ... acho que vc vai ter q fazer um script ... pensei em algo assim

acho até que da um loop
pega a primeira coluna e salva no arquivo [primeira-linha].txt
...
...
pega a segunda coluna e salva no arquivo [primeira-linha].txt


depois vc junta com o "paste"
paste Bairro.txt Cidade.txt Cliente.txt Endereço.txt Estado.txt ID.txt Número.txt Telefone.txt > arquivo-final.txt 






------------------------------------------| Linux User #621728 |-----------------------------------------
" Nem sempre é amigo aquele que te tira do buraco !!! ( Saddam Hussein )"
------------------------------------------| Linux User #621728 |-----------------------------------------



5. Re: Existe alguma forma de ordenar um arquivo texto por colunas da ESQ. para a DIR. ? [RESOLVIDO]

Mestre Kame
mlgrassi

(usa Debian)

Enviado em 09/07/2017 - 23:50h

Ainda não resolve amigo, pois não ordena dinamicamente, logo se o arquivo vier com as colunas trocadas, dará na mesma.


6. Re: Existe alguma forma de ordenar um arquivo texto por colunas da ESQ. para a DIR. ?

Fernando
phoemur

(usa Debian)

Enviado em 10/07/2017 - 00:21h

arquivo.txt

Telefone;Endereço;Nome do Cliente;ID;Bairro;Estado;Cidade;Número
(21)3234-1234;Rua João Paulo Segundo;Rogério da Silva;04321;Tijuca;RJ;Rio de Janeiro;444
(48)2431-5465;Av. Beira Mar;Francisco Xavier;05354;Jurerê;SC;Florianópolis;43


script.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import csv

campos = ['Bairro', 'Cidade', 'Nome do Cliente', 'Endereço', 'Estado', 'ID', 'Número', 'Telefone']

with open('arquivo.txt', mode='r') as infile, open('reordered.txt', mode='a') as outfile:
writer = csv.DictWriter(outfile, fieldnames=campos, delimiter=';')
writer.writeheader()
for row in csv.DictReader(infile, delimiter=';'):
writer.writerow(row)


Saída: reordered.txt

Bairro;Cidade;Nome do Cliente;Endereço;Estado;ID;Número;Telefone
Tijuca;Rio de Janeiro;Rogério da Silva;Rua João Paulo Segundo;RJ;04321;444;(21)3234-1234
Jurerê;Florianópolis;Francisco Xavier;Av. Beira Mar;SC;05354;43;(48)2431-5465


Esse script em python vai pegar a entrada do arquivo.txt e ordenar na sequencia que está na variável campos e salvar em reordered.txt
Pode estar em qualquer ordem que a saída vai ser sempre no mesmo padrão definido na variável campos.

A única observação é que o nome dos campos tem que bater certinho com o arquivo de entrada se não dá erro.
Pra contornar isso precisaria de uma lógica um pouco mais complexa (detectar os campos através da primeira linha de arquivo.txt) e depois ordenar da forma que você quiser. Dá pra ter uma idéia...

Um abraço


7. Re: Existe alguma forma de ordenar um arquivo texto por colunas da ESQ. para a DIR. ?

Perfil removido
removido

(usa Nenhuma)

Enviado em 10/07/2017 - 00:49h

Essa coisa não vem pelo menos com cabeçalhos na colunas? Essa primeira linha com Nome ... Telefone ... existe?

Dá para criar uma verificação de posição de cabeçalho. Depende, criar um array.

linha_cabecalho=($(head -1 documento.txt | tr ';' ' ') 


head -1 pega a primeira linha do arquivo. Depois tr troca os separadores de ponto-e-vírgula por espaços. Tudo executado em subshell $(...) . O par de parêntesis a mais (...) serve para transformar a saída subshell $(...) no array linha_cabecalho.

O problema agora é indexar a saída. As colunas do arquivo se comparadas com os índices do array diferem de uma unidade. Dá para tentar algo assim:

cont=1
for i in ${linha_cabecalho[@]}
do
cut -d';' -f $cont documento.txt > Campo-$i.txt
let cont++
done


O loop passa um a um nos elementos do vetor. A variável cont serve como índices de campos para o comando cut cortar os campos conforme o cabeçalho. A saída é jogada em campos com os nomes dos cabeçalhos.

Pronto. Agora os campos estão separados por arquivos. Você só precisará juntá-los na ordem que quiser. Para isto será usado o comando paste.

paste -d';' arquivo1.txt arquivo2.txt arquivo3.txt ... > arquivo_final.txt
rm Campo-*.txt


A opção -d';' cola os campos um do lado do outro separando-os por ;. Use espaço em branco ou outra coisa para criar um formato adequado.

Depois dos arquivos colados e padronizados, você poderá usar o comando sort. Veja antes se até aqui deu certo.
Favor adaptar.


8. Re: Existe alguma forma de ordenar um arquivo texto por colunas da ESQ. para a DIR. ? [RESOLVIDO]

Mauriciodez
Mauriciodez

(usa Debian)

Enviado em 10/07/2017 - 01:43h

mlgrassi escreveu:

Ainda não resolve amigo, pois não ordena dinamicamente, logo se o arquivo vier com as colunas trocadas, dará na mesma.


justamente por vir colunas trocadas é que resolveria .. só resolver umas paradas aqui que faço esse script !!!



------------------------------------------| Linux User #621728 |-----------------------------------------
" Nem sempre é amigo aquele que te tira do buraco !!! ( Saddam Hussein )"
------------------------------------------| Linux User #621728 |-----------------------------------------



9. Re: Existe alguma forma de ordenar um arquivo texto por colunas da ESQ. para a DIR. ? [RESOLVIDO]

Mauriciodez
Mauriciodez

(usa Debian)

Enviado em 10/07/2017 - 01:53h

mlgrassi escreveu:

Ainda não resolve amigo, pois não ordena dinamicamente, logo se o arquivo vier com as colunas trocadas, dará na mesma.


justamente por vir colunas trocadas é que resolveria .. só resolver umas paradas aqui que faço esse script !!!



------------------------------------------| Linux User #621728 |-----------------------------------------
" Nem sempre é amigo aquele que te tira do buraco !!! ( Saddam Hussein )"
------------------------------------------| Linux User #621728 |-----------------------------------------



10. Re: Existe alguma forma de ordenar um arquivo texto por colunas da ESQ. para a DIR. ? [RESOLVIDO]

Mestre Kame
mlgrassi

(usa Debian)

Enviado em 11/07/2017 - 16:14h

listeiro_037 escreveu:

Essa coisa não vem pelo menos com cabeçalhos na colunas? Essa primeira linha com Nome ... Telefone ... existe?

Dá para criar uma verificação de posição de cabeçalho. Depende, criar um array.

linha_cabecalho=($(head -1 documento.txt | tr ';' ' ') 


head -1 pega a primeira linha do arquivo. Depois tr troca os separadores de ponto-e-vírgula por espaços. Tudo executado em subshell $(...) . O par de parêntesis a mais (...) serve para transformar a saída subshell $(...) no array linha_cabecalho.

O problema agora é indexar a saída. As colunas do arquivo se comparadas com os índices do array diferem de uma unidade. Dá para tentar algo assim:

cont=1
for i in ${linha_cabecalho[@]}
do
cut -d';' -f $cont documento.txt > Campo-$i.txt
let cont++
done


O loop passa um a um nos elementos do vetor. A variável cont serve como índices de campos para o comando cut cortar os campos conforme o cabeçalho. A saída é jogada em campos com os nomes dos cabeçalhos.

Pronto. Agora os campos estão separados por arquivos. Você só precisará juntá-los na ordem que quiser. Para isto será usado o comando paste.

paste -d';' arquivo1.txt arquivo2.txt arquivo3.txt ... > arquivo_final.txt
rm Campo-*.txt


A opção -d';' cola os campos um do lado do outro separando-os por ;. Use espaço em branco ou outra coisa para criar um formato adequado.

Depois dos arquivos colados e padronizados, você poderá usar o comando sort. Veja antes se até aqui deu certo.
Favor adaptar.



Amigo, gostei muito de sua ideia, mas me da uma dica para a seguinte linha:
linha_cabecalho=($(head -1 documento.txt | tr ';' ' ')

Mas na verdade encontrei um problema aqui. Quando o vetor é populado com o comando acima, existe um campo da coluna que possui espaços, que no caso é o campo Nome do Cliente. Ocorre que como o delimitador default em vetores é o espaço em branco, cada palavra do campo será atribuída a um índice, ou seja, índice x=Nome índice y=do e índice z=Cliente.
Na tentativa de contornar este problema, eu alterei o comando acima para utilizar o sed como substituidor de strings ao invés do tr, para incluir áspas duplas em cada campo para estes serem interpretados como devem ser:

linha_cabecalho=($(head -1 documento.txt | sed "s/^\|$/\"/g" | sed "s/\;/\"\ \"/g"))

Isto irá gerar a saída: "Telefone" "Endereço" "Nome do Cliente" "ID" "Bairro" "Estado" "Cidade" "Número"

Até aí tudo bem. O problema ocorre quando isso é atribuído ao vetor linha_cabecalho, onde as áspas duplas são interpretadas como caractere e não como intervalo de dados.

Alguma sugestão para resolver isso?


11. Re: Existe alguma forma de ordenar um arquivo texto por colunas da ESQ. para a DIR. ? [RESOLVIDO]

Marcelo Oliver
msoliver

(usa Debian)

Enviado em 11/07/2017 - 18:06h

mlgrassi escreveu:

listeiro_037 escreveu:

Essa coisa não vem pelo menos com cabeçalhos na colunas? Essa primeira linha com Nome ... Telefone ... existe?

Dá para criar uma verificação de posição de cabeçalho. Depende, criar um array.

linha_cabecalho=($(head -1 documento.txt | tr ';' ' ') 


head -1 pega a primeira linha do arquivo. Depois tr troca os separadores de ponto-e-vírgula por espaços. Tudo executado em subshell $(...) . O par de parêntesis a mais (...) serve para transformar a saída subshell $(...) no array linha_cabecalho.

O problema agora é indexar a saída. As colunas do arquivo se comparadas com os índices do array diferem de uma unidade. Dá para tentar algo assim:

cont=1
for i in ${linha_cabecalho[@]}
do
cut -d';' -f $cont documento.txt > Campo-$i.txt
let cont++
done


O loop passa um a um nos elementos do vetor. A variável cont serve como índices de campos para o comando cut cortar os campos conforme o cabeçalho. A saída é jogada em campos com os nomes dos cabeçalhos.

Pronto. Agora os campos estão separados por arquivos. Você só precisará juntá-los na ordem que quiser. Para isto será usado o comando paste.

paste -d';' arquivo1.txt arquivo2.txt arquivo3.txt ... > arquivo_final.txt
rm Campo-*.txt


A opção -d';' cola os campos um do lado do outro separando-os por ;. Use espaço em branco ou outra coisa para criar um formato adequado.

Depois dos arquivos colados e padronizados, você poderá usar o comando sort. Veja antes se até aqui deu certo.
Favor adaptar.



Amigo, gostei muito de sua ideia, mas me da uma dica para a seguinte linha:
linha_cabecalho=($(head -1 documento.txt | tr ';' ' ')

Mas na verdade encontrei um problema aqui. Quando o vetor é populado com o comando acima, existe um campo da coluna que possui espaços, que no caso é o campo Nome do Cliente. Ocorre que como o delimitador default em vetores é o espaço em branco, cada palavra do campo será atribuída a um índice, ou seja, índice x=Nome índice y=do e índice z=Cliente.
Na tentativa de contornar este problema, eu alterei o comando acima para utilizar o sed como substituidor de strings ao invés do tr, para incluir áspas duplas em cada campo para estes serem interpretados como devem ser:

linha_cabecalho=($(head -1 documento.txt | sed "s/^\|$/\"/g" | sed "s/\;/\"\ \"/g"))

Isto irá gerar a saída: "Telefone" "Endereço" "Nome do Cliente" "ID" "Bairro" "Estado" "Cidade" "Número"

Até aí tudo bem. O problema ocorre quando isso é atribuído ao vetor linha_cabecalho, onde as áspas duplas são interpretadas como caractere e não como intervalo de dados.

Alguma sugestão para resolver isso?


Boa tarde.
Para resolver o problema da ARRAY CABEÇALHO, faça:
OIFS="$IFS"
CAMPOS=$(sed -n '1p' arquivo)
IFS=";" read -a CMP <<< "$CAMPOS"
IFS="$OIFS"
for ((x=0;x<${#CMP[@]};x++));do echo "${CMP[$x]}";done
Telefone
Endereço
Nome do Cliente
ID
Bairro
Estado
Cidade
Número

Em ordem ALFABETICA:
for ((x=0;x<${#CMP[@]};x++));do echo "${CMP[$x]}";done|sort
Bairro
Cidade
Endereço
Estado
ID
Nome do Cliente
Número
Telefone

Marcelo Oliver


12. Re: Existe alguma forma de ordenar um arquivo texto por colunas da ESQ. para a DIR. ? [RESOLVIDO]

Mestre Kame
mlgrassi

(usa Debian)

Enviado em 11/07/2017 - 18:32h

Muitíssimo obrigado!!!

Tudo foi de grande ajuda e consegui solucionar meu problema.

Um grande abraço a todos!!!



01 02



Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts