[root@server]# awk '!seen[$0]++' out.txt > cleaned
awk: (FILENAME=out.txt FNR=8547098) fatal error: internal error
Aborted
[root@server]#
«Сервер» имеет: 8 ГБ ОЗУ + 16 ГБ SWAP, x> 300 ГБ свободного места, amd64, настольный ЦП. Научный Linux 6.6. На нем больше ничего не работает, чтобы сделать LOAD. Awk прерывается через несколько секунд .. out.txt составляет ~ 1,6 ГБайт. GNU Awk 3.1.7.
Вопрос : Как я могу удалить дубликаты строк, сохраняя порядок строк? Случай также важен, например: «А» и «а» - это две разные строки, должны их сохранить. Но «а» и «а» дублируют, нужен только первый.
Ответ может быть что угодно .. если awk не подходит для этого .. тогда perl / sed .. в чем может быть проблема?
[root@server]# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 61945
max locked memory (kbytes, -l) 99999999
max memory size (kbytes, -m) unlimited
open files (-n) 999999
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 99999999
cpu time (seconds, -t) unlimited
max user processes (-u) 61945
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
[root@server]#
Обновление: я пробовал это на машине RHEL, она не прерывается, но у меня не было времени ждать, пока она закончится .. почему SL linux отличается от RHEL?
Обновление: я пытаюсь на Ubuntu 14 виртуальных гостей ... пока это работает! Это не проблема ulimit: mawk 1.3.3
root@asdf-VirtualBox:~# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 51331
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 51331
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
root@asdf-VirtualBox:~#
источник
awk
версии в двух машинах?out.txt
? Работает ли та же команда, если вы попробуете ее на меньшем файле? Сколько пользователей на машине? Было ли достаточно памяти для процесса? Что-нибудь особенное в строке 8547098 входного файла?Ответы:
Я сомневаюсь, что это будет иметь значение, но, на всякий случай, вот как сделать то же самое в Perl:
Если проблема заключается в сохранении уникальных строк в памяти, это будет иметь ту же проблему, что и
awk
вы. Итак, другой подход может быть:Как это устроено:
В системе GNU,
cat -n
перед каждой строкой будет добавляться номер строки после некоторого количества пробелов, за которым следует символ <tab> .cat
направляет это входное представление вsort
.sort
Параметр 's'-k2
дает указание рассматривать только символы от второго поля до конца строки при сортировке иsort
разбивает поля по умолчанию на пробелы (илиcat
вставленные пробелы и <tab> ) .Когда следует
-k1n
,sort
сначала рассматривает 2-е поле, а затем - в случае идентичных-k2
полей - 1-е поле, но сортируется численно. Таким образом, повторяющиеся строки будут отсортированы вместе, но в порядке их появления.uniq
который, как говорят, игнорирует первое поле (-f1
и также разделены пробелами), что приводит к списку уникальных строк в исходном файле и возвращается обратноsort
.sort
сортирует по первому полю (cat
вставленный номер строки) численно, возвращает порядок сортировки к тому, что было в исходном файле, и направляет эти результатыcut
.cut
удаляет номера строк, которые были вставленыcat
. Это достигается путемcut
печати только из 2-го поля до конца строки (аcut
разделителем по умолчанию является символ <tab> ) .Проиллюстрировать:
источник
sort
! Но большинство из нихsort
могут сделать этоuniq
сами, поэтому вы можете использовать шорт-сценарийsort -uk2 | sort -bk1,1n
sort
? Я думал, что-u
это особенность GNU.-u
и указать, что он должен игнорировать 1-е поле? Согласноman sort
,-u
это не один из возможных вариантов-f
, поэтому я не думаю, что он может быть использован здесь.РЕДАКТИРОВАТЬ 1: это действительно работает? (сравнение)
Случай 1 : 100_000_000 случайных чисел (5 цифр каждое), 566 Мбайт, 31_212 различных значений:
Случай 2 : 50_000_000 случайных чисел (по 10 цифр каждый), 516 Мбайт, 48_351_464 различных значений:
(следующие цифры не очень точны):
sol2 с кешем это:
Сортировку также можно оптимизировать, добавив опцию кэширования (не сделано).
Один быстрый вывод:
sort
это фантастическая команда!источник
sort -uk2
иsort -nk1,1
разные. Первый считает от 2-го ключа до конца строки, второй рассматривает только первый ключ. Вы должны поменять свойsort -nk1
там - это может быть даже быстрее, но это, безусловно, будет более надежным. Кстати, вот такие красивые коробки.cat -n
что вкладка ? Я не знаю, как работает эта команда.cat -n
transfrom другline
вspaces + the number + \t + line
- формат идеально подходит для сортировки и резкиЯ использовал
BINMODE = rw: чтобы довольные окончания строки были довольны. (Я живу в смешанной среде ОС)
Логика проста.
Если текущей строки нет в ассоциативном массиве, добавьте ее в ассоциативный массив и напечатайте для вывода.
При таком подходе могут быть ограничения памяти. Для очень больших файлов и наборов файлов я использовал эти варианты, используя хранилище файлов, чтобы обойти ограничения.
источник
Сохраняющая порядок семантика вашей задачи обладает удивительным свойством: вы можете подразделить проблему. Вы можете сделать
split -l 1000000
на входном файле; 1000000 строк, которые он производит, имеют лексически упорядоченные имена, что хорошо; затем уникальные кусочки; а затем (в качестве второго прохода) унифицируйте выходы тех.Это решает проблему нехватки памяти (путем ограничения потребности в памяти) за счет превращения ее в многопроходное решение.
В частности:
Генерация входных данных:
Разделите входные данные:
Запустите uniqifier одновременно (сохранит все уникальные строки ввода в памяти):
Запустите uniqifier для разделенных фрагментов (сохраните в памяти только уникальные строки ввода для каждого фрагмента), а затем уменьшите в качестве второго прохода:
Для сравнения:
Я не знаю соотношения уникальных и неуникальных строк в вашем вводе, а также того, насколько хорошо смешаны входные строки - поэтому необходимо выполнить некоторые настройки с точки зрения количества необходимых вам разделенных файлов.
источник
Другой подход (заслуживающий публикации в качестве отдельного ответа) заключается в следующем: вместо метода разделения файлов, который создает временные файлы, выполняйте пакетирование в самом программном обеспечении uniqifier. Например, используя реализацию Ruby uniqifier для пояснительных целей:
Идея состоит в том, чтобы очищать хэш-наборы так часто. Тогда это становится итеративным:
Таким образом, вы можете запускать эту ограниченную версию несколько раз, пока количество строк не изменится от одной итерации к следующей.
Обратите внимание, что этот метод capped-uniqm не зависит от языка: вы можете очищать
lines_seen
массив каждые N строк независимо от того, используете ли вы awk, python, perl, C ++ и т. Д. Для всех этих языков существуют методы set-clear; Я считаю,awk
чтоdelete
это нестандартно, но распространено.источник