Разделить CSV на несколько файлов, содержащих заданное количество уникальных значений полей

Как новичок в awk, я могу разбить данные с уникальным значением на

awk -F, '{print >> $1".csv";close($1)}' myfile.csv

Но я хотел бы разделить большой файл CSV на основе дополнительного условия, которое представляет собой появление уникальных значений в определенном столбце.

В частности, с вводом

111,1,0,1
111,1,1,1
222,1,1,1
333,1,0,0
333,1,1,1
444,1,1,1
444,0,0,0
555,1,1,1
666,1,0,0

Я бы хотел, чтобы выходные файлы были

111,1,0,1
111,1,1,1
222,1,1,1
333,1,0,0
333,1,1,1

а также

444,1,1,1
444,1,0,1
555,1,1,1
666,1,0,0

каждое из которых содержит три (в данном случае) уникальных значения 111,222,333 и 444,555,666 соответственно в первом столбце. Любая помощь будет оценена по достоинству.


person Francis    schedule 25.03.2015    source источник
comment
Непонятно, каково условие разделения файла.   -  person    schedule 25.03.2015
comment
вы имеете в виду 3 значения uniq на файл?   -  person Kent    schedule 25.03.2015
comment
да, я только что отредактировал пост.   -  person Francis    schedule 25.03.2015


Ответы (2)


Это поможет, и я нахожу его довольно читаемым и легким для понимания:

awk -F',' 'BEGIN { count=0; filename=1 }
            x[$1]++==0 {count++}
            count==4 { count=1; filename++}
            {print >> filename".csv"; close(filename".csv");}' file

Мы начинаем с нашего счетчика с 0 и нашего имени файла с 1. Затем мы подсчитываем каждое уникальное значение, которое мы получаем из первого столбца, и всякий раз, когда оно четвертое, мы сбрасываем счет и переходим к следующему имени файла.

Вот некоторые образцы данных, которые я использовал, они только ваши с некоторыми дополнительными строками.

~$ cat test.txt
111,1,0,1
111,1,1,1
222,1,1,1
333,1,0,0
333,1,1,1
444,1,1,1
444,0,0,0
555,1,1,1
666,1,0,0
777,1,1,1
777,1,0,1
777,1,1,0
777,1,1,1
888,1,0,1
888,1,1,1
999,1,1,1
999,0,0,0
999,0,0,1
101,0,0,0
102,0,0,0

И запускаем awk так:

~$ awk -F',' 'BEGIN { count=0; filename=1 }
            x[$1]++==0 {count++}
            count==4 { count=1; filename++}
            {print >> filename".csv"; close(filename".csv");}' test.txt

Мы видим следующие выходные файлы и контент:

~$ cat 1.csv
111,1,0,1
111,1,1,1
222,1,1,1
333,1,0,0
333,1,1,1

~$ cat 2.csv
444,1,1,1
444,0,0,0
555,1,1,1
666,1,0,0

~$ cat 3.csv
777,1,1,1
777,1,0,1
777,1,1,0
777,1,1,1
888,1,0,1
888,1,1,1
999,1,1,1
999,0,0,0
999,0,0,1

~$ cat 4.csv
101,0,0,0
102,0,0,0
person zzevannn    schedule 25.03.2015
comment
Как вы сказали, я понимаю код, как только его прочту, спасибо! - person Francis; 26.03.2015

этот однострочный текст поможет:

awk -F, -v u=3 -v i=1 '{a[$1];
   if (length(a)>u){close(i".csv");++i;delete a;a[$1]}print>i".csv"}' file 

Вы меняете значение u=3 на x, чтобы получить x уникальных значений для каждого файла.

Если вы запустите эту строку со своим входным файлом, вы должны получить 1.csv and 2.csv

Изменить (добавить тестовый результат):

kent$  ll
total 4.0K
drwxr-xr-x  2 kent kent  60 Mar 25 18:19 ./
drwxrwxrwt 19 root root 580 Mar 25 18:18 ../
-rw-r--r--  1 kent kent  90 Mar 25 17:57 f

kent$  cat f
111,1,0,1
111,1,1,1
222,1,1,1
333,1,0,0
333,1,1,1
444,1,1,1
444,0,0,0
555,1,1,1
666,1,0,0

kent$  awk -F, -v u=3 -v i=1 '{fn=i".csv";a[$1];if (length(a)>u){close(fn);++i;delete a;a[$1]}print>fn}' f  

kent$  head *.csv
==> 1.csv <==
111,1,0,1
111,1,1,1
222,1,1,1
333,1,0,0
333,1,1,1

==> 2.csv <==
444,1,1,1
444,0,0,0
555,1,1,1
666,1,0,0
person Kent    schedule 25.03.2015