extrair / copiar intervalos de colunas do arquivo de dados grande

2

Eu estava tentando preparar arquivos de dados de um arquivo grande, extraindo colunas e colando em um novo arquivo.

O número de colunas dos dados fornecidos é muito grande. Eu quero preparar um número de arquivos de dados, dividindo os dados.
Eu estava tentando o script abaixo, mas não está funcionando. Espero que o erro seja devido à especificação de intervalos de colunas para copiar.

#!/bin/bash

paste <(awk '{print $1,$2,$3,...$19,$20}' Precipitation.csv ) > aaaaa1
paste <(awk '{print $21,$22,$23,...$39,$40}' Precipitation.csv ) > aaaaa2 
paste <(awk '{print $41,$42,$43,...$99,$100}' Precipitation.csv ) > aaaaa3 

Você poderia me ajudar a corrigir o código?

    
por AiB 05.08.2014 / 09:43

5 respostas

5

Isso parece um caso em que cut será melhor que awk :

cut -d , -f1-20 Precipitation.csv > aaa1
cut -d , -f21-40 Precipitation.csv > aaa2
cut -d , -f41-100 Precipitation.csv > aaa3

-d , especifica o delimitador (uma vírgula, já que a entrada é chamada de CSV, mas você pode alterar isso). -f N-M seleciona campos N a M inclusive para estar na saída. Se houver vírgulas embutidas em qualquer campo, isso irá quebrar. Nesse caso, você provavelmente precisará de um analisador CSV real, embora seja possível hackear algo se isso realmente não for possível.

A saída usará o mesmo delimitador da entrada. O GNU cut suporta uma opção --output-delimiter=STRING para definir um delimitador diferente, mas não acho que outros Faz. O cut do FreeBSD inclui um -w opção dividida por espaço em branco que está mais próxima de qual awk faz por padrão. Se você quiser um desses comportamentos em outro lugar, transformar o delimitador antes / depois é provavelmente sua melhor aposta.

    
por 05.08.2014 / 09:53
2

Um follow-up na resposta de Michael Homer :

Para evitar a leitura do arquivo várias vezes com shells suportando a substituição do processo ( ksh , zsh , bash ):

 tee < Precipitation.csv >(cut -d, -f1-20 > aaa1) >(cut -d, -f21-40 > aaa2) | 
   cut -d, -f41- > aaa3
    
por 05.08.2014 / 16:14
1

com perl :

perl -F',' -anle 'print join ",", @F[0..19]' Precipitation.csv > aaa1
perl -F',' -anle 'print join ",", @F[20..39]' Precipitation.csv > aaa2
perl -F',' -anle 'print join ",", @F[40..99]' Precipitation.csv > aaa3
    
por 05.08.2014 / 10:28
1

Como eu entendo seu problema, isso deve ser tudo o que você precisa - e tudo é processado em um único fluxo, então você deve lidar com o arquivo grande de maneira muito mais eficiente.

Eu fiz um pequeno teste sobre isso:

{   sed -e '/\n\n/{s///w aaa3
    d' -e '};s/,/\n/20;P;G;D' |
    sed -ne 'w aaa1' -e 'n;p'
} <<DATA > aaa2
$(
    seq -s, 100 | tee - - - -
)
DATA

Depois imprimi os resultados como:

for f in 1 2 3
do  printf '\n%s\n' aaa$f
    cat aaa$f
done

E sucesso!

aaa1
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20

aaa2
21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40
21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40
21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40
21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40
21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40

aaa3
41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100
41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100
41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100
41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100
41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100
    
por 07.08.2014 / 02:02
0

Isso fornece melhor desempenho, pois estamos lendo o arquivo de entrada apenas uma vez

awk '{out1=$1; for(i=2; i<=20; i++) {out1 = (out1 FS $i)}
  out2=$21; for(i=22; i<=40; i++) {out2=(out2 FS $i)}
  out3=$41; for(i=42; i<=100; i++) {out3=(out3 FS $i)}
  print out1 > "aaaaa1"; print out2 > "aaaaa2"; print out3 > "aaaaa3"}' Precipitation.csv

ou você pode digitar todos os números de campo no comando abaixo. Substitua '...' por todos os números de campo necessários

awk '{print $1,$2,$3,...$19,$20 > "aaaaa1";
  print $21,$22,$23,...$39,$40 > "aaaaa2";
  print $41,$42,$43,...$99,$100 > "aaaaa3"}' Precipitation.csv
    
por 06.08.2014 / 08:52