Isolar colunas de um arquivo texto [RESOLVIDO]

1. Isolar colunas de um arquivo texto [RESOLVIDO]

Rafael Carlos Treml
rafael.carlos

(usa Debian)

Enviado em 17/10/2012 - 18:47h

Boa tarde!

gostaria de isolar algumas colunas de um arquivo texto. Veja abaixo um trecho do arquivo:

7702270346 RADIO VDO-DAYTON CD711 UN 0101 A C? 0INDEF 374,024 828,46 ,00 ,00
7702270347 RECEPTOR DE RADIODIFUSÃO DO T UN 0101 A C? 0INDEF 391,02 866,10 ,00 ,00
7702270348 CONTROLE REMOTO INFLAVERMELHO UN 0101 A C? 0INDEF 33,082 82,59 ,00 ,00
7702270350 RADIO VDO CD 2703 MP3 RN UN 0101 A C? 0INDEF 515,543 1.141,92 ,00 ,00
7702270351 MECANISMO DE ACIONAMENTO DO V UN 0101 A B1 4A18-01-A01 490,007 1.085,36 4.341,43 1.960,03

Gostaria de deixá-lo de forma que eu conseguisse visualizar o código, o nome da peça e a penultima coluna:

7702270346 RADIO VDO-DAYTON CD711 ,00
7702270347 RECEPTOR DE RADIODIFUSÃO DO T ,00
7702270348 CONTROLE REMOTO INFLAVERMELHO ,00
7702270350 RADIO VDO CD 2703 MP3 RN ,00
7702270351 MECANISMO DE ACIONAMENTO DO V 4.341,43

Estou teno muita dificuldade neste tipo de lógica, pois não consegui identificar nenhum padrão para que um comando só (tentei com o sed) pudesse verificar. A dificuldade maior é para pegar os dados da penúltima coluna.

Alguém consegue me dar uma ideia?

abraços!


  


2. MELHOR RESPOSTA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 19/10/2012 - 02:50h

rafael.carlos escreveu:

Boa tarde!

gostaria de isolar algumas colunas de um arquivo texto. Veja abaixo um trecho do arquivo:

7702270346 RADIO VDO-DAYTON CD711 UN 0101 A C? 0INDEF 374,024 828,46 ,00 ,00
7702270347 RECEPTOR DE RADIODIFUSÃO DO T UN 0101 A C? 0INDEF 391,02 866,10 ,00 ,00
7702270348 CONTROLE REMOTO INFLAVERMELHO UN 0101 A C? 0INDEF 33,082 82,59 ,00 ,00
7702270350 RADIO VDO CD 2703 MP3 RN UN 0101 A C? 0INDEF 515,543 1.141,92 ,00 ,00
7702270351 MECANISMO DE ACIONAMENTO DO V UN 0101 A B1 4A18-01-A01 490,007 1.085,36 4.341,43 1.960,03

Gostaria de deixá-lo de forma que eu conseguisse visualizar o código, o nome da peça e a penultima coluna:

7702270346 RADIO VDO-DAYTON CD711 ,00
7702270347 RECEPTOR DE RADIODIFUSÃO DO T ,00
7702270348 CONTROLE REMOTO INFLAVERMELHO ,00
7702270350 RADIO VDO CD 2703 MP3 RN ,00
7702270351 MECANISMO DE ACIONAMENTO DO V 4.341,43

Estou teno muita dificuldade neste tipo de lógica, pois não consegui identificar nenhum padrão para que um comando só (tentei com o sed) pudesse verificar. A dificuldade maior é para pegar os dados da penúltima coluna.

Alguém consegue me dar uma ideia?

abraços!


Como não? Se você contar as colunas de trás para diante, tem, ao que me parece, uma estrutura bem consistente: sempre nove colunas depois do nome. Como antes do nome você só tem uma coluna, pode usar algo do seguinte tipo.

perl -pe 's/^\s*(\S+)\s+(\S.*?)\s+(\S+\s+){7}(\S+)\s+\S+\s*$/$1 $2 $4\n/;' 


EXPLICAÇÃO: "^" significa início da linha; "\s", espaço em branco; "\S", qualquer caráter exceto espaço em branco, ".", qualquer caráter; e "$", fim da linha. Os parênteses indicam composições em bloco, e fazem com que o mecanismo de expressões regulares guardem aquele bloco para referência futura. Os contadores de repetição são: "*", que significa a maior quantidade possível de repetições, com zero ou mais ocorrências; "+", para a maior quantidade possível de repetições, com uma ou mais ocorrências; "*?", que quer dizer a menor quantidade possível, com zero ou mais ocorrências; e "{n}", que significa exatamente n ocorrências.

Sabedor disso, dá para ver que eu busco uma linha que pode começar ou não com espaços em branco, e retenho a primeira coluna, formada somente por não-espaços, seguida obrigatoriamente por um ou mais espaços, quando então eu retenho uma sequência iniciada por um não-espaço e que se estende com uma quantidade desconhecida de caracteres quaisquer (tal quantidade só será conhecida quando o restante da linha for examinada, a seguir), e então procuro por uma sequência de espaços seguida de sete ocorrências de um bloco formado por sequência de não-espaços seguidos de espaços, seguida, então, por mais uma coluna, que eu retenho, de não-espaços, um bloco de espaços, outro de não-espaços, e eventuais espaços no fim da linha. Se tal composição, no fim das contas, ocorrer, eu a substituo pelos valores retidos do primeiro, segundo e quarto blocos (o terceiro, que são as sete repetições de colunas antes da penúltima, é retido, mas eu só usei os parênteses para indicar a composição, não por ter interesse nos valores), separados por espaços e com uma quebra de linha.

Dá para fazer com sed, em lugar de Perl. Só que sed, por não implementar (por default, no caso do GNU sed, ou de modo algum, no caso do sed tradicional) expressões regulares estendidas, não tem os operadores de repetição "+", "*?" e "+?", que eu considero úteis, nem formas abreviadas como "\s" para indicar qualquer tipo de espaço ou "\S" para qualquer não-espaço. Fica, portanto, feio de escrever e de ler, como mostrado abaixo.

sed -e 's/^[ 	]*\([^ 	][^ 	]*\)[ 	][ 	]*\([^ 	].*\)[ 	][ 	]*\([^ 	][^ 	]*[ 	][ 	]*\)\{7\}\([^ 	][^ 	]*\)[ 	][ 	]*[^ 	][^ 	]*[ 	]*$/\1 \2 \4/' 


Dentro de cada par de colchetes (com ou sem o sinal de negação "^") eu tenho um espaço seguido de uma tabulação (pois eu não sei que tipo de espaço em branco existe no arquivo original). Note como eu tive de trocar o operador de repetição "+", que significa "um ou mais", por uma ocorrência fixa da expressão entre colchetes seguida pela mesma expressão com repetição do tipo "zero ou mais", indicada por "*". Também, no sed o significado especial dos parênteses e das chaves se dá precedendo-os com o caráter "\", que é exatamente o oposto do que ocorre com expressões regulares estendidas do POSIX e do Perl.

Se você tiver certeza de que seu sed é o da GNU, pode optar por usar expressões regulares estendidas. Nesse caso, sua linha de comando pode ser a seguinte.

sed -re 's/^[[:space:]]*([^[:space:]]+)[[:space:]]+([^[:space:]].*)[[:space:]]+([^[:space:]]+[[:space:]]+){7}([^[:space:]]+)[[:space:]]+[^[:space:]]+[[:space:]]*$/\1 \2 \4/;' 


(Mas eu ainda prefiro fazer com Perl, que é mais sucinto e claro.)

3. Re: Isolar colunas de um arquivo texto [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 17/10/2012 - 19:30h

A virgula pode ser o seu padrão inicial.




4. Re: Isolar colunas de um arquivo texto [RESOLVIDO]

Sergio Teixeira - Linux User # 499126
Teixeira

(usa Linux Mint)

Enviado em 17/10/2012 - 20:30h

O delimitador provavelmente será o ponto-e-vírgula ou algum caracter especial, já que a vírgula nesse exemplo está sendo usada para separar casas decimais.
(Delimitadores geralmente são caracteres não imprimiveis).
O caminho das pedras portanto será ler a string caracter por caracter até encontrar o delimitador, e tratar convenientemente os campos (tudo o que estiver entre tais delimitadores) - nesse caso, dois delimitadores seguidos indicariam que há um campo vazio entre eles.
Alguns arquivos (antigamente todos) podem também conter headers (cabeçalhos), e caracteres especiais indicadores de BOF (início do arquivo) e EOF (fim do arquivo). Parece que seu arquivo de exemplo não tem nada disso, então é somente ler caracter por caracter, o que facilita em muto os procedimentos.
Boa sorte!


5. Re: Isolar colunas de um arquivo texto [RESOLVIDO]

Rafael Carlos Treml
rafael.carlos

(usa Debian)

Enviado em 18/10/2012 - 21:02h

obrigado pela força! vou continuar tentando!

abraços!


6. Re: Isolar colunas de um arquivo texto [RESOLVIDO]

Rafael Carlos Treml
rafael.carlos

(usa Debian)

Enviado em 24/10/2012 - 10:18h

obrigado Paulo! seu post foi muito esclarecedor!
já consegui fazer!
abraços!






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts