Проблема: у меня достаточно большой репозиторий (тысячи файлов, сотни тысяч строк).
У меня есть текстовый файл с ~ 5000 строк.
Мне нужно найти строки в текстовом файле, которые не появляются где-либо еще в хранилище.
Есть ли инструмент или умный способ использовать grep, который может эффективно найти этот ответ?
Спасибо за любую помощь
Ответы:
Решение было разработано в
bash
Ubuntu 16.04.2 LTS.Алгоритм
Этот раздел является образовательным. Вы можете найти весь сценарий в конце моего ответа.
Сначала сделайте копию вашего текстового файла. Это важно, файл, с которым мы будем работать, будет перезаписан, и для этого есть причина. Настройте переменные в соответствии с вашим случаем:
Вам понадобится несколько временных файлов.
Следующая команда сохранит все (ну, почти все, прочитайте вместе) шаблоны, которые появятся в хранилище, в первый временный файл. Смотрите,
man grep
чтобы расшифровать команду. Также решите, нужно ли вам добавить-i
опцию вgrep
. Первыйuniq
является необязательным, он используется для предварительного сокращения данных, к которым идетsort
.Если вышеприведенная команда напечатает
0
,$patterns
файл является вашим окончательным результатом, независимо от ошибок, указанных ниже, и вы должны удалить только временные файлы.Есть подводные камни
grep
, вы будете иметь дело с ними в одно мгновение. Хорошо знать, кто они.foobar
иfoo
как шаблоны,foobar
в репозитории будут совпадатьfoobar
только.foobar
иbarbaz
как шаблоны,foobarbaz
в репозитории будут совпадатьfoobar
только.foobarbaz
иbar
как шаблоны,foobarbaz
в репозитории будут совпадатьfoobarbaz
только.Из-за этих ловушек
$tmpf1
могут не содержаться все шаблоны, которые действительно появляются в хранилище (то есть он может не содержатьbarbaz
из второй ловушки).Теперь вам нужно выбрать все те строки
$patterns
, которые якобы не были найдены в хранилище. Обратите внимание, что вы должны соответствовать целые строки, следовательно-x
.В этот момент
$tmpf2
будет ваш конечный результат, но из-за этих ошибок он может содержать слишком много строк (например,barbaz
из второй ошибки). Хитрость заключается в том, чтобы использовать$tmpf2
в качестве нового файла шаблона и повторить процесс! Призовите:затем перейдите к первому
grep
. Повторите эту процедуру , пока вы не получите0
отwc
там. Как я уже говорил, когда0
возвращается, ваш результат в$patterns
.В конце удалите временные файлы:
КПД
У меня есть 200 тыс. Текстовых файлов, 4,5 млн строк, всего 300 мегабайт. Это HTML-документы с простыми заголовками и форматированием, почти простой текст на английском языке. Я взял 3k самых распространенных английских слов в качестве шаблонов и добавил несколько строк мумбо-юмбо.
Сначала
grep
потребовалось несколько минут, чтобы прочитать данные с жесткого диска и работать, затем около двух минутsort
. Но каждая последующая итерация занимала считанные секунды благодаря кешированию и$patterns
уменьшению его количества.Мое оборудование - Core i7 и 8 ГБ оперативной памяти. Ваши шаблоны и файлы могут значительно отличаться и влиять на время выполнения. Тем не менее, я думаю, что есть шанс, что вы решите задачу за несколько минут.
Сценарий
Это реализация вышеуказанного алгоритма. Еще одна дополнительная функция: она берет шаблоны из
stdin
, печатает результат наstdout
. В этом случае вам не нужно копировать ваш текстовый файл. Сценарий не является надежным.Сохраните следующий код как
findUnused.sh
, затемchmod a+x findUnused.sh
.Использование (обратите внимание, есть перенаправления):
источник