Найти нужные строки во множестве документов

На самом деле это единственный раздел про unix на этом форуме

Модераторы: /dev/random, Модераторы разделов

Frg7777
Сообщения: 4

Найти нужные строки во множестве документов

Сообщение Frg7777 »

Товарищи, подскажите

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

Василий Иванов
Николай Петров
Федор Зорин
Максим Котов
Николай Белов
Максим Матов
...

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

ПС. Может есть лучший способ как выполнить эту задачу максимально быстро с учетом многогигабайтности данных?
Спасибо сказали:
Аватара пользователя
Hephaestus
Сообщения: 3729
Статус: Многоуважаемый джинн...
ОС: Slackware64-14.1/14.2

Re: Найти нужные строки во множестве документов

Сообщение Hephaestus »

Навскидку как-то так:

Создаем текстовый файл с ключами поиска (по одному ключу на строку)
patterns.txt

Код: Выделить всё

Василий
Николай
Максим
Поиск по различным файлам:
find -name "*.txt" -exec grep -f patterns.txt '{}' \; >>newfile.txt
Насколько это будет (не)быстро, судить не берусь, решение, можно сказать, "в лоб".
Сам таким иногда пользуюсь, но у меня объемы поиска существенно меньше.

Нужно ещё учесть кодировку файлов.
И не плохо бы, чтобы искомые файлы/каталоги имели хоть какой-то общий корень, если такой есть, тогда поиск начинать оттуда,
иначе много лишних файлов придется просматривать и это может дать побочные результаты.

Если же есть возможность составить список просматриваемых файлов (с полными путями),
то можно натравить grep конкретно на файлы из этого списка, что исключит ложные срабатывания.
Пускай скрипят мои конечности.
Я - повелитель бесконечности...
Мой блог
Спасибо сказали:
Аватара пользователя
olecya
Сообщения: 721
ОС: debian, fedora (i3-wm)

Re: Найти нужные строки во множестве документов

Сообщение olecya »

Hephaestus писал:
20.10.2020 14:03
find -name "*.txt" -exec grep -f patterns.txt '{}' \; >>newfile.txt
В grep есть опция -r и --include=\*.txt
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 19483
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Найти нужные строки во множестве документов

Сообщение Bizdelnick »

Hephaestus писал:
20.10.2020 14:03
Создаем текстовый файл с ключами поиска (по одному ключу на строку)
patterns.txt

Код: Выделить всё

Василий
Николай
Максим
Это неэффективно. Нужно заякорить:

Код: Выделить всё

^Василий
^Николай
^Максим
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
Hephaestus
Сообщения: 3729
Статус: Многоуважаемый джинн...
ОС: Slackware64-14.1/14.2

Re: Найти нужные строки во множестве документов

Сообщение Hephaestus »

Bizdelnick писал:
20.10.2020 15:33
Это неэффективно. Нужно заякорить:

Код: Выделить всё

^Василий
^Николай
^Максим
Вообще, это зависит от исходных файлов.
Если там строки типа

Код: Выделить всё

Василий Иванов
Николай Петров
тогда да.

Но если вдруг будет

Код: Выделить всё

Иванов Василий Петрович
Петров Николай Семенович
что совсем не исключено,
тогда строки нужно обрамлять пробелами:

Код: Выделить всё

 Василий 
 Николай 
 Максим 
причем без концевых пробелов, например, "Петр" зацепится, как часть отчества "Петрович".
В любом случае, я показал лишь идею. Понятно, что итоговый вариант будет отличаться.
olecya писала:
20.10.2020 14:28
В grep есть опция -r и --include=\*.txt
В данной конкретной задаче так, наверное, лучше. Вывод grep с подсветкой получится.
А в общем случае у find возможностей отбора побольше будет.
Я эту самую опцию --include у grep даже когда-то пробовал, кажется, но как-то не прижилась. Уже не помню, почему.
Пускай скрипят мои конечности.
Я - повелитель бесконечности...
Мой блог
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 19483
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Найти нужные строки во множестве документов

Сообщение Bizdelnick »

Hephaestus писал:
20.10.2020 18:39
Вообще, это зависит от исходных файлов.
Я исхожу из того, что они такие, как описал ТС.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
olecya
Сообщения: 721
ОС: debian, fedora (i3-wm)

Re: Найти нужные строки во множестве документов

Сообщение olecya »

Hephaestus писал:
20.10.2020 18:39
Уже не помню, почему.
Может скушать много ресурсов и подвесить соседей, есть такое.
Добавлено (19:19):
Это я о рекурсивной опции со множеством сложных паттернов. Через find будет с любыми вариантами плавнее
Спасибо сказали:
Аватара пользователя
s.xbatob
Сообщения: 1139
ОС: Fedora

Re: Найти нужные строки во множестве документов

Сообщение s.xbatob »

только задача какая-то странная. Что, в файлах только имена, а поиск не требуется морфологический? Ну, нашлось — что дальше нужно?
Спасибо сказали:
Frg7777
Сообщения: 4

Re: Найти нужные строки во множестве документов

Сообщение Frg7777 »

Спасибо!
Мне тут подсказали, что на больших объемах для ускорения можно использовать другие утилиты, в частности ag (Silver Searcher). Будет гораздо быстрее.

https://beyondgrep.com/feature-comparison/

Кого лучше? И как запрос будет выглядеть тогда?
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 19483
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Найти нужные строки во множестве документов

Сообщение Bizdelnick »

Frg7777 писал(а):
06.11.2020 12:34
Кого лучше?
Вряд ли будет большая разница, в любом случае упрётесь в скорость чтения с диска. Впрочем, можете поэкспериментировать.
Frg7777 писал(а):
06.11.2020 12:34
И как запрос будет выглядеть тогда?
Регулярки будут выглядеть точно так же в любом синтаксисе. Что basic, что extended, что perl.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 2040
ОС: Gentoo

Re: Найти нужные строки во множестве документов

Сообщение ormorph »

codesearch в помощь.
Просто проиндексировать каталог с файлами(cindex), и выполнить поиск(csearch).
Для Gentoo писал когда то ебилд, для тестовой ветки с гита, теперь добавил ебилд для версии 1.2.0.
Спасибо сказали:
Аватара пользователя
UnixNoob
Сообщения: 909
ОС: Slackware

Re: Найти нужные строки во множестве документов

Сообщение UnixNoob »

А с помощью awk данную задачу не решить? Я просто про bash читаю, там оно как раз для работы с файлами предлагается.
«Хорошо сформулированная проблема — наполовину решенная проблема».Чарлз Кеттеринг
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 2040
ОС: Gentoo

Re: Найти нужные строки во множестве документов

Сообщение ormorph »

UnixNoob писал:
06.11.2020 19:10
А с помощью awk данную задачу не решить?
Может и можно, но поиск во множестве подкаталогов не вариант, все равно нужно будет использовать find.
Тогда уж лучше использовать grep -R. А еще лучше и быстрее использовать ripgrep тыц.
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 19483
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Найти нужные строки во множестве документов

Сообщение Bizdelnick »

ormorph писал(а):
06.11.2020 19:52
А еще лучше и быстрее использовать ripgrep
Чем лучше и почему быстрее?
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 2040
ОС: Gentoo

Re: Найти нужные строки во множестве документов

Сообщение ormorph »

Bizdelnick писал:
06.11.2020 21:46
Чем лучше и почему быстрее?
Оно вообще отрабатывает быстрее чем grep, ну и может вывести просто список файлов в которых присутствует указанное слово, что делает очень удобным в скриптах:

Shell

$ rg -t txt --files-with-matches PATTERN
Ну и для решения данной задачи достаточно одной команды:

Shell

$ rg -NI -j4 -t txt PATTERN /PATH >file.txt
Где j4 количество потоков - нужно указать своё количество ядер.
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 19483
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Найти нужные строки во множестве документов

Сообщение Bizdelnick »

ormorph писал(а):
06.11.2020 21:58
Оно вообще отрабатывает быстрее чем grep
Быстрее читает файлы с диска?

Программа не может работать «вообще быстрее», время выполнения зависит от массы факторов. Она может быстрее компилировать регулярки, но при этом они будут медленнее работать, или наоборот. Может работать быстрее с простыми регулярками, но тормозить со сложными, или наоборот. Скорость может зависеть от размера файлов, объёма ОЗУ, кешей процессора, ещё кучи факторов. Короче, без теста в конкретных условиях такие заявления совершенно безосновательны.
ormorph писал(а):
06.11.2020 21:58
может вывести просто список файлов в которых присутствует указанное слово
И зачем это надо в данном случае?
Добавлено (22:17):
ormorph писал(а):
06.11.2020 21:58
для решения данной задачи достаточно одной команды
С grep -R тоже достаточно одной команды.
ormorph писал(а):
06.11.2020 21:58
Где j4 количество потоков - нужно указать своё количество ядер.
Вот вообще не факт, что выполнение в несколько потоков не замедлит работу вместо того, чтобы ускорить, если файлы читаются с HDD. Будут только головку туда-сюда перепозиционировать.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 2040
ОС: Gentoo

Re: Найти нужные строки во множестве документов

Сообщение ormorph »

Bizdelnick писал:
06.11.2020 22:15
Вот вообще не факт, что выполнение в несколько потоков не замедлит работу вместо того, чтобы ускорить, если файлы читаются с HDD. Будут только головку туда-сюда перепозиционировать.
Кто знает, вот попробовал несколько раз запустить:
Spoiler

Shell

$ time grep -Rh --include=\*.txt word program/ >/dev/null

real 0m0,174s
user 0m0,105s
sys 0m0,069s
$ time rg -NI -j4 -t txt word program/>/dev/null

real 0m0,087s
user 0m0,223s
sys 0m0,048s
$ time grep -Rh --include=\*.txt word program/ >/dev/null

real 0m0,128s
user 0m0,068s
sys 0m0,060s
$ time rg -NI -j4 -t txt word program/>/dev/null

real 0m0,083s
user 0m0,207s
sys 0m0,064s
Смотреть по real, получается rg отрабатывает быстрее, но у меня там не так много файлов, по этому нужно глядеть там где больше файлов.
Вот поробовал специально первый поиск grep и rg в каталоге /usr/include(кеширования ещё небыло):
Spoiler

Shell

$ time grep -Rh include /usr/include/ >/dev/null

real 0m19,676s
user 0m0,531s
sys 0m3,188s

$ time rg -NI -j4 include /usr/include/ >/dev/null

real 0m0,856s
user 0m1,028s
sys 0m1,024s
Как видно скорость обработки на порядок выше.
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 19483
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Найти нужные строки во множестве документов

Сообщение Bizdelnick »

ormorph писал(а):
06.11.2020 22:48
вот попробовал несколько раз запустить
Это у Вас на многогигабайтном каталоге так быстро отработало? Тогда, безусловно, беру свои слова обратно.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 2040
ОС: Gentoo

Re: Найти нужные строки во множестве документов

Сообщение ormorph »

Bizdelnick писал:
06.11.2020 23:00
Но время работы самой программы — это вовсе не real, а user.
Ээ , вот это рассказывать не надо, я же лично наблюдал сколько занял поиск в каталоге /usr/include. Как раз grep и отработал где то 19 секунд, в то время как у rg это заняло менее секунды.
Bizdelnick писал:
06.11.2020 23:00
Проход rg — уже «горячий», они брались из кеша
Ок сейчас попробую на другом компе выполнить данные команды в другом порядке, сначала rg потом grep, ну и там диск будет немного медленней.
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 19483
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Найти нужные строки во множестве документов

Сообщение Bizdelnick »

ormorph писал(а):
06.11.2020 22:48
Вот поробовал специально первый поиск grep и rg в каталоге /usr/include(кеширования ещё небыло)
Так только такой случай ТСу и имеет смысл рассматривать. Он, вроде как, не собирается без конца поиск гонять, да и не закешируется его многогигабайтное хозяйство полностью. А сравнения обеих программ с пустым кешем нет.
Добавлено (23:19):
ormorph писал(а):
06.11.2020 23:15
я же лично наблюдал сколько занял поиск в каталоге /usr/include.
Он занял real. Но за вычетом user и sys останется iowait, который почти всё время и занял.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 2040
ОС: Gentoo

Re: Найти нужные строки во множестве документов

Сообщение ormorph »

В общем протестировал grep и rg, получились такие результаты:
Spoiler

Shell

# time grep -Rh include /usr/include/ >/dev/null

real 1m42,866s
user 0m0,237s
sys 0m1,232s

# time rg -NI -j4 include /usr/include/ >/dev/null

real 1m26,898s
user 0m0,611s
sys 0m1,664s

# time rg -NI include /usr/include/ >/dev/null

real 1m26,084s
user 0m0,686s
sys 0m1,579s
Протестировал на обычном жестком диске(не ssd), пришлось каждый раз перезагружать комп, чтобы кеш обновлялся, обе утилиты используют один и тот же кеш. Все таки rg будет быстрее grep-а.

А вот при использовании ssd разница в несколько раз:
Spoiler

Shell

# time rg -NI -j4 -t txt include /usr/include/ >/dev/null

real 0m1,004s
user 0m0,221s
sys 0m0,234s

# time grep -Rh include /usr/include/ >/dev/null

real 0m18,947s
user 0m0,349s
sys 0m2,282s
Спасибо сказали:
Аватара пользователя
olecya
Сообщения: 721
ОС: debian, fedora (i3-wm)

Re: Найти нужные строки во множестве документов

Сообщение olecya »

Решила проверить по результату, перед каждым тестом презагружалась:

Shell

time grep -ohr 'include\|exclude' --include=\*.h /usr/include/ >log.grep
real 0m8,256s
user 0m0,120s
sys 0m0,337s
time grep -ohr 'include\|exclude' --include=\*.h /usr/include/ >log.grep
real 0m8,189s
user 0m0,118s
sys 0m0,332s

time rg -INo -j4 'include|exclude' --glob \*.h /usr/include/ >log.rg
real 0m8,666s
user 0m0,189s
sys 0m0,428s
time rg -INo -j4 'include|exclude' --glob \*.h /usr/include/ >log.rg
real 0m8,061s
user 0m0,179s
sys 0m0,434s

diff <(sort log.rg) <(sort log.grep)
Только жесткий диск, 4 ядра, 4 потока
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 2040
ОС: Gentoo

Re: Найти нужные строки во множестве документов

Сообщение ormorph »

На счет вывода ssd пардон, там команду не ту сделал, там искало в txt файлах, по этому так быстро))
Spoiler

Shell

# time rg -NI -j4 include /usr/include/ >/dev/null

real 0m16,386s
user 0m1,261s
sys 0m2,529s
С регулярками позже попробую у себя, пока не до этого.
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 19483
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Найти нужные строки во множестве документов

Сообщение Bizdelnick »

ormorph писал(а):
07.11.2020 00:00
получились такие результаты
Ну вот это уже похоже на правду.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Frg7777
Сообщения: 4

Re: Найти нужные строки во множестве документов

Сообщение Frg7777 »

Вобщем я так понял, что с учетом много гигабайтности даннх grep будет медленым.

Как тогда будет выглядеть команда с какой-то из этих альтернатив grep
https://beyondgrep.com/feature-comparison/

чтобы (напомню) найти во всех вложеных папках во всех этих сотнях гигабайт текстовых документов только строки содержащие нужные имена, например, только строки с "Василий", "Николай", "Максим" и составит из этих строк новый файл .txt
?
Спасибо сказали:
Frg7777
Сообщения: 4

Re: Найти нужные строки во множестве документов

Сообщение Frg7777 »

Добавлю, что данные хранятся не на ssd а на обычном жестком диске
Спасибо сказали:
Аватара пользователя
olecya
Сообщения: 721
ОС: debian, fedora (i3-wm)

Re: Найти нужные строки во множестве документов

Сообщение olecya »

Frg7777 писал(а):
08.11.2020 10:13
Вобщем я так понял, что с учетом много гигабайтности даннх grep будет медленым.
Медленной будет состваляющая для открытия и чтения каждого файла которая будет одинакова как для grep так и для rg

Код: Выделить всё

grep -hrw '^\(Василий\|Николай\|Максим\)' --include=\*.txt /path/to/dir/ >log.grep
rg -IN -j4 '^(Василий|Николай|Максим)\b' --glob \*.txt /path/to/dir/ >log.rg
Если уверенности нет, что имена будут только в начале строк то удалите якорь начала строки ^ из шаблона
Последний раз редактировалось olecya 08.11.2020 13:49, всего редактировалось 3 раза.
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 19483
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Найти нужные строки во множестве документов

Сообщение Bizdelnick »

Frg7777 писал(а):
08.11.2020 10:13
Вобщем я так понял, что с учетом много гигабайтности даннх grep будет медленым.

Как тогда будет выглядеть команда с какой-то из этих альтернатив grep
Они все будут медленными. Максимум несколько процентов выиграете, даже в 10% верится с трудом. Если поиск нужно будет гонять часто, а не раз в квартал, займитесь лучше переводом этого хозяйства в нормальную индексируемую БД.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали: