Извлечение строк ключом из очень большого файла

Вы могли попытаться отправить сигнал SIGCONT в процесс, но как rozcietrzewiacz упоминания, Вы, возможно, должны сделать некоторый обман с дескрипторами файлов, если процесс требует терминального доступа.

уничтожьте - ПРОДОЛЖЕНИЕ СЛЕДУЕТ pid

Если это все еще подходит как T, затем этому, вероятно, нужен ввод данных пользователем.

6
23.08.2012, 02:28
3 ответа

Используя awk должно быть достаточно эффективным - это обеспечивает встроенные ассоциативные массивы, где ключевое время поиска логарифмически пропорционально количеству ключей (Вашей справочной таблицы - который является относительно маленьким в Вашем примере).

Для Вашего входа это было бы:

42M * log2(1.5M) -> 42M * 20 key comparisons 

(где M означает 10^6),

В случае, если Ваш awk использует хеш-таблицы, каждый ключевой поиск только стоил бы постоянного количества времени.

Пример эффективного awk основывал решение (использующий разделителя полей по умолчанию):

$ awk 'ARGIND == 1 { a[$1] = 1; next } a[$1] { print $0 }' keys.dat largefile.dat

Так как оба исходных данных отсортированы, Вы могли записать сценарий, который будет более эффективным (со временем выполнения, масштабирующимся линейно с обоими входными размерами файла). Но это стоило бы большего количества времени, программируя его.

Или Вы могли использовать join которые ожидают отсортированные файлы, как введено - ограничение - то, что Ваш ключ должен быть в алфавитном порядке отсортирован - и возможно необходимо настроить выходной формат. Например:

$ join -j1 keys.dat largefile.dat

Использовать -t настраивать разделителя полей и -o скорректировать выходной формат.

Это должно работать вовремя линейный к входному размеру.

5
27.01.2020, 20:24
  • 1
    Извините за мою бестактность редактирования.. Я сделал быстрый Ctrl-A, Ctrl-V (даже не смотря), для замены всего одной строкой, но я был в неправильном ответе :(.. Это - хорошая вещь, у нас есть откат... соединение –  Peter.O 22.08.2012, 22:33
  • 2
    похоже точно, что я хочу, за исключением того, что мои поля являются фиксированной шириной, и соединение, кажется, только поддерживает строки, разграниченные отдельными символами. –  joebolte 22.08.2012, 22:45

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

При помощи \x01 (или любой уникальный однобайтовый символ) как временный разделитель полей, записями можно более легко управлять.

join -t$'\x01' <(sed -r 's/.{9}/&\x01/' main) <(cut -b -9 keys) |sed -r 's/(.{9})./\1/'

maxschlepzig's awk пример был быстрее для 45 000 000 записей, но он перестал работать на большем файле. Сколько свободной RAM Вы имеете?

Вот результаты:

45,000,000 unique records, 1,500,000 keys
=========================
awk

real    0m31.971s
user    0m28.782s
sys     0m2.972s

join

real    0m53.733s
user    0m54.255s
sys     0m0.708s

(2x45) 90,000,000 records, 1,500,000 keys
=========================
awk
awk: (FILENAME=main2 FNR=54334297) fatal: assoc_lookup: bucket->ahname_str: can't allocate 11 bytes of memory (Cannot allocate memory)

join

real    1m35.306s
user    1m34.754s
sys     0m1.344s

===================
4
27.01.2020, 20:24

Принятие это - основанный на строке файл, grep должно быть довольно эффективным. Использовать -f keyfile и -F для фиксированных строк:

grep -F -f keys textfile

Примечание: учтите предупреждение о ложных положительных сторонах PeterO в комментариях ниже.

1
27.01.2020, 20:24
  • 1
    -F проблематично, если Вы не соответствуете всей записи: например: grep -Ff <(echo 123456) <(echo 633322 data:123456789) возвращает запись, ключ которой на самом деле 633322 –  Peter.O 23.08.2012, 07:28
  • 2
    PS... Я только что синхронизировал его против данных, используемых в моем ответе, для которого нет никакой возможности столкновения. Это быстро; начинание работу в 7,5 секунд и 9,2 секунд для 45M и 90M файлы respecively.. Жаль о проблеме столкновения... (Интересно если -F может быть привязан на запуске из записи?)... Я попробовал regex (без-F), но он увяз. –  Peter.O 23.08.2012, 08:10
  • 3
    Соответствие только на столбце ключа должно решить эти проблемы. Я обновил ответ. –  Thor 23.08.2012, 11:44
  • 4
    Это удивительно медленно.. Это выставляет подобранные записи на устойчивом уровне, и я уверен, что это доберется там, но я не могу ждать 625 часов для него для окончания 1,5 миллионов соответствий в моих данных тестирования :).. т.е. приблизительно 1,5 секунды на запись... Это - действительно удивление. –  Peter.O 23.08.2012, 14:51
  • 5
    Мог это быть вторым sed быть очень медленным? Могли Вы пробовать: ... | sed 's/^/NR==/' | awk -f - textfile в конце канала. –  Thor 23.08.2012, 15:08

Теги

Похожие вопросы