2015-07-19 6 views
2

У меня есть CSV, который выглядит следующим образом *:Расщепление один CSV на несколько файлов на основе значения поля

system,subject,value1,value2 
example.org,thing 1,100,4 
exmaple.org,thing 2,90,0 
example.com,thing 1,200,0 
example.com,thing 5,10,10 

заголовке нас на самом деле не включены, но показанные здесь, чтобы сделать его легче читать пример.

И я хочу, чтобы разделить, что на два файла:

example.org.csv с:

thing 1,100,4 
thing 2,90,0 

example.com.csv с:

thing 1,200,0 
thing 5,10,10 

мое текущее решение работает таким образом:

while read line; do 
    SYSTEM=$(echo "$line" | cut -d, -f1) 
    NOTTHESYSTEM=$(echo "$line" | cut -d, -f2-) 
    echo "${NOTTHESYSTEM}" >> "${SYSTEM}.csv" 
done <$INPUT 

Но это работает очень неэффективно и плохо работает с большими файлами.

В цифрах это означает, что файл 52050/9 МБ требует около 250 секунд для завершения раскола.

Любые предложения по улучшению сценария выше приветствуются.

Приветствия

ответ

2

Использование awk будет проще:

awk 'BEGIN{FS=OFS=","} {print $2, $3, $4 > $1 ".csv"}' "$INPUT" 

Проверка:

cat example.org.csv 
thing 1,100,4 
thing 2,90,0 

cat example.com.csv 
thing 1,200,0 
thing 5,10,10 
+1

Гораздо быстрее - спасибо. Это теперь работает в 0.3s вместо 250s. – pagid

+0

Можно ли добавить этап gzip с помощью этого метода, чтобы все выходные файлы были бы gzipped? – Sahas

+0

Просто переадресуйте вывод в файл и вызовите 'gzip', чтобы его застегнуть. – anubhava

1

Один из способов сделать это, предполагая, что у вас есть достаточно небольшое количество систем:

cut -d, -f1 file.csv | \ 
    sort -u | \ 
    while read -r system; do 
     fgrep -w "$system" file.csv | cut -d, -f2- >"$system".csv 
    done 
Смежные вопросы