Удалите вторую строку, где первые несколько столбцов идентичны в большом файле

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

A 1 abc A 1 def A 2 ttt B 2 ppp B 2 qqq 

Я бы хотел сохранить первую строку, когда первые два ключа идентичны, поэтому примерно так:

 A 1 abc A 2 ttt B 2 ppp 

Я нашел предыдущий вопрос, который решил это. Тем не менее, мой файл составляет 1,2 ГБ, и я сопоставляю первые 19 столбцов. Поэтому, когда я запускаю это:

  awk '!array[$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19]++' infile > outfile 

Я получаю это:

 cmd. line:2: (FILENAME=infile FNR=287807) fatal: dupnode: r->stptr: can't allocate memory (Not enough memory) 

Очевидно, я не могу разбить файл для обработки, потому что я не знаю, где дубликаты. Я готов обменять скорость на память, чтобы решить эту проблему. (Файл составляет около 1,6 миллиона строк).

Как кажется, ваш файл сортируется:

 sort -m -u -k 1,2 < file 

-m для merge не пытается сортировать файл, но с -u (для уникального ) в сочетании с -k 1,2 для указания ключа сортировки, состоящего из первых 2 полей (используйте -k 1,19 для первых 19 поля), мы удаляем дубликаты в первых двух полях.

Если файл не отсортирован (по крайней мере, на этих двух полях), просто снимите -m . В конечном итоге результат будет отсортирован. Сортировка будет дорогостоящей, но она должна быть в порядке, так как sort использует временные файлы для сортировки больших файлов (вам нужно свободное место на диске /tmp (или $TMPDIR )).

Будет ли объединение столбцов, которые идентичны для работы индекса? С приведенным выше, например. мы могли бы сделать –

  awk '{ind=""; for(i=1; i<3; i++) {ind=ind" "$i } if (!arr[ind]) arr[ind]=$3 } END{for (i in arr) print i, arr[i]}' A 1 abc A 2 ttt B 2 ppp 

вам, конечно, нужно будет изменить цикл выше, чтобы объединить необходимые вам индексы.

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

 BEGIN{ xd=""; } { id=$1; if (id != xd) { for (x in arr) { print x,arr[x]; } delete arr; #Each time the field one changes its value xd=id; } ind=""; for (i=1; i<3; i++) { ind=ind $i; } if (!arr[ind]) { arr[ind]=$3; } } END { for (x in arr) { print x,arr[x]; } } 

Вывод:

 $ awk -f script.awk file.txt A1 abc A2 ttt B2 ppp 

Попробуйте это:

 awk '_a[$1" "$2]++==0' < filename