Extraindo dados da estrutura de arquivos complexa

5

Eu tenho um arquivo txt que é um despejo de um banco de dados, que contém uma entrada por linha. A estrutura é assim:

1500
29/03/2010 
18
02
09
47
17
45
28.248
0
0.01
130
12.721
7908
298,809
YES
3.046.550,39
6.500.000,00
17,444,222


1501
30/03/2010
27
54
28
50
22
03
37.223
0
0.00
97
22,466
7379
421.90
NO
20,262,429
25,000,000.01
17,995,281.33


... the third record starts here

O banco de dados contém 21 campos. As linhas anteriores mostram o despejo de dois registros desse banco de dados. As linhas em branco representam campos em branco no banco de dados.

O primeiro campo (F0) é o número que você vê 1500, 1501 ...

O segundo campo (F1) é uma data no formato dia, mês, ano.

Os campos F2, F3, F4, F5, F6 e F7 são seis números inteiros.

O que eu preciso é extrair F0, F2, F3, F4, F5, F6, F7 deste arquivo, criando uma linha para cada um.

Dados os dois registros acima, o arquivo final seria

1500,18,02,09,47,17,45
1501,27,54,28,50,22,03

Eu sei como fazer isso usando um script bash que terá milhas de extensão e interagirá sobre cada linha, etc. Mas também sei que o unix é um saco de truques, especialmente o comando sed e que isso provavelmente pode ser feito com uma linha simples. Eu adoro aprender coisas novas, então eu pergunto a vocês que são deuses no Unix, como eu faço isso?

Eu estou no OSX Mavericks. Obrigado.

    
por SpaceDog 14.04.2014 / 22:30

3 respostas

3

Aqui está uma maneira:

$ perl -000ne '@f=split(/\n/); print join(",",@f[0,2..7]) , "\n"' file.txt  
1500,18,02,09,47,17,45
1501,27,54,28,50,22,03

Explicação:

  • -000 : ativa "modo de parágrafo", define o delimitador de campo perl como \n\n , novas linhas consecutivas. Isso significa que ele tratará cada um dos seus registros como uma única linha.

  • @f=split(/\n/); : divida a linha atual (o registro) em novas linhas e salve como a matriz @f . Este array agora contém cada campo do seu registro. Isso significa que a fatia da matriz @f[0,2..8] conterá os campos 0 e 2 a 8.

  • print join ",",@f[0,2..8] , "\n"' : isso unirá a fatia da matriz com vírgulas e imprimirá a sequência resultante seguida por uma nova linha.

por 14.04.2014 / 22:37
5

Usando awk :

awk '
  BEGIN {
    fields[1]
    fields[3]
    fields[4]
    fields[5]
    fields[6]
    fields[7]
    last_field=8
  }
  ( NR%21 in fields ) { printf($0",") }
  NR%21==last_field' in_file.txt

Ou melhor ainda:

awk '
  NR%21 ~ /^(1|3|4|5|6|7)$/ { printf($0",") }
  NR%21==8' in_file.txt

O GNU sed tem uma boa extensão para combinar com a enésima linha depois de uma dada, que é útil aqui. Não funcionará no OSX, mas para se divertir:

sed -n '
  1~21 { h }
  3~21,7~21 { H }
  8~21 { H; g; s/\n/,/gp }' in_file
    
por 14.04.2014 / 22:56
0

Se os seus dados sempre tiverem algum número de campos ausentes ( isto é, 2 ou mais retornos difíceis entre registros), você poderá simplesmente:

$ awk -v RS="\n{2,}" -F"\n" -v OFS="," '{print $1, $3, $4, $5, $6, $7, $8}' file.txt
1500,18,02,09,47,17,45
1501,27,54,28,50,22,03
    
por 15.04.2014 / 03:08