поиск статического списка фиксированных строк в огромном количестве файлов - PullRequest
0 голосов
/ 09 мая 2018

У меня есть большое количество фиксированных строк (~ 5 миллионов), которые я хочу найти во многих файлах.

Я видел, что два наиболее часто используемых алгоритма поиска строк с использованием конечного набора шаблонов: Aho-Corasick и Commentz-Walter .

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

После некоторых исследований я обнаружил множество статей, в которых говорится, что Commentz-Walter в реальных сценариях имеет тенденцию быть быстрее, чем Aho-Corasick ( Article1 , Article2 ), и это также алгоритм за GNU-grep .

Я пытался использовать grep -F также параллельно (взято из здесь ):

free=$(awk '/^((Swap)?Cached|MemFree|Buffers):/ { sum += $2 }
          END { print sum }' /proc/meminfo)
percpu=$((free / 200 / $(parallel --number-of-cores)))k
parallel --pipepart -a regexps.txt --block $percpu --compress \
grep -F -f - -n bigfile

и кажется, что проблема слишком большая. Я получаю эту ошибку:

grep: memory exhausted
  1. Я думал о попытке разбить список шаблонов на несколько файлов и запустить grep несколько раз для одного и того же файла - но это кажется неуклюжим. Есть ли другое решение? или я неправильно запускаю grep?
  2. Запустив алгоритм Commentz-Walter, grep должен выполнить некоторую предварительную обработку. Я предполагаю, что запуск grep с одним и тем же файлом шаблона в двух разных файлах приведет к тому, что grep выполнит один и тот же этап предварительной обработки дважды. Есть ли способ запустить grep для списка файлов и заставить его запускать предварительную обработку шаблонов только один раз?
  3. Есть ли хорошая реализация Commentz-Walter в c \ c ++? я только нашел код в Python ( здесь )?

--- Обновление ---

Согласно некоторым комментариям, я пытался протестировать различные реализации Aho-Corasick c \ c ++ ( Komodia , Cjgdev , chasan ), но ни один из них не смог справились с примером из 5 миллионов наборов шаблонов (у всех были проблемы с памятью (ошибка сегментации / переполнение стека)) - они работают на небольших наборах. Файл примера был сгенерирован этим кодом:

with open(r"C:\very_large_pattern", 'w') as out:
for _ in range(0, 5000000):
    out.write(str(uuid.uuid4()) + '\n')

У кого-нибудь есть предложения по реализации, которая может обрабатывать эти числа?

1 Ответ

0 голосов
/ 01 июня 2019

Вот простое решение, которое должно быть быстрым.

Поместите ваши строки фиксированной длины для поиска, один за другим, в файл и отсортируйте файл. Назовите этот файл S.

Для каждого файла, который вы хотите найти, выполните:

  1. Если длина строк для поиска равна k, разбейте файл на все возможные строки длины k. Вызовите этот файл B. Например, если k = 5, и файл для поиска:

    abcdefgh
    123
    123456
    

    Файл поврежденных строк будет:

    abcde
    bcdef
    cdefg
    defgh
    12345
    23456
    

    Теперь, чтобы узнать положение каждой прерывистой строки в оригинальном файле, добавьте номера ее строк и столбцов в файл B. Например,

    abcde 1 1
    bcdef 1 2
    cdefg 1 3
    defgh 1 4
    12345 3 1
    23456 3 2
    
  2. Сортировать B и объединить его с S. Вызвать полученный файл M. Например, если S равно:

    23456
    cdefg
    

    М будет:

    12345 3 1
    23456
    23456 3 2
    abcde 1 1
    bcdef 1 2
    cdefg
    cdefg 1 3
    defgh 1 4
    
  3. Извлечь из M все вхождения строк S, найденных в файле. Например:

    23456
    23456 3 2
    cdefg
    cdefg 1 3
    

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

Я не знаю, с какой ОС вы работаете, но описанные выше действия, скорее всего, можно выполнить с помощью таких команд, как sort, awk, grep и т. Д.

...