Разделить файл без разделения строк, начинающихся с одинаковых значений в Unix - PullRequest
0 голосов
/ 14 мая 2018

У меня есть отсортированный файл .csv, который выглядит примерно так:

AABB1122,ABC,BLAH,4
AABB1122,ACD,WHATEVER,1
AABB1122,AGT,CAT,4
CCDD4444,AYT,DOG,4
CCDD4444,ACG,MUMMY,8
CCEE4444,AOP,RUN,5
DDFF9900,TUI,SAT,33
DDFF9900,WWW,INDOOR,5

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

Здесь я получу три файла:

x00000:

AABB1122,ABC,BLAH,4
AABB1122,ACD,WHATEVER,1
AABB1122,AGT,CAT,4

x00001:

CCDD4444,AYT,DOG,4
CCDD4444,ACG,MUMMY,8

x00002:

CCEE4444,AOP,RUN,5
DDFF9900,TUI,SAT,33
DDFF9900,WWW,INDOOR,5 

Мои реальные данные имеют размер около 7 гигабайт и содержат более 100 миллионов строк.Я хочу разбить его на файлы по 100K строк или ~ 6 МБ.Я в порядке с использованием размера файла или номера строк для разделения.

Я знаю, что я могу использовать «сортировку» для разделения, например:

split -a 5 -d -1 2

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

Я думаю, что мне, вероятно, нужен awk, но даже после прочтения руководства я не уверен, что делать дальше.

Помощь приветствуется!Спасибо!

Ответы [ 2 ]

0 голосов
/ 14 мая 2018

С csplit, если доступно

С учетом данных

csplit -s infile %^A% /^C/ %^C% /^D/ /^Z/ {*}
0 голосов
/ 14 мая 2018

Сценарий awk:

BEGIN   { FS = ","  }
!name   { name = sprintf("%06d-%s.txt", NR, $1) }

count >= 2 && prev != $1  {
    close(name)
    name = sprintf("%06d-%s.txt", NR, $1)
    count = 0
}

{
    print >name
    prev = $1
    ++count
}

Запуск этого на данных данных создаст три файла:

$ awk -f script.awk file.csv

$ cat 000001-AABB1122.txt
AABB1122,ABC,BLAH,4
AABB1122,ACD,WHATEVER,1
AABB1122,AGT,CAT,4

$ cat 000004-CCDD4444.txt
CCDD4444,AYT,DOG,4
CCDD4444,ACG,MUMMY,8

$ cat 000006-CCEE4444.txt
CCEE4444,AOP,RUN,5
DDFF9900,TUI,SAT,33
DDFF9900,WWW,INDOOR,5

Я произвольно выбрал использование номера строки из оригиналафайл, из которого была взята первая строка, вместе с данными первого поля в этой строке в качестве имени файла.

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

Последний блок просто печатаетк текущему имени файла, запоминает первое поле в переменной prev и увеличивает счетчик.

Блок BEGIN инициализирует разделитель полей (до чтения первой строки) и блок !nameустанавливает начальное имя выходного файла (при чтении самой первой строки).


Чтобы получить именно те имена файлов, которые у вас есть в очередиstion, используйте

name = sprintf("x%05d", ++n)

, чтобы установить имя выходного файла в обоих местах, где это делается.

...