LINUX.ORG.RU
решено ФорумTalks

Есть кто-то шарящий в fzf и grep?

 ,


0

1

Подскажите, плиз, такую штуку: директории есть пачка логов за год по дням 01012023.log - 31122023.log. Каждый лог состоит из строк типа:

01.01.2023 (time) (login) (etc) IP address (CONNECT)

Запускаю команду:

grep -r "" * | fzf --exact

Изначально выхлоп включает имена файлов и все это отсортировано по ним как надо:

01012023.log:01.01.2023 (time) (login) (etc) IP address (CONNECT)
01022023.log:01.02.2023 (time) (login) (etc) IP address (CONNECT)
01032023.log:01.03.2023 (time) (login) (etc) IP address (CONNECT)
01042023.log:01.04.2023 (time) (login) (etc) IP address (CONNECT)

Но как только ввожу что угодно для поиска, сортировка ломается. А по идее, должно точно так же продолжать сортировать с новой выборкой. Что я делаю не так?

Что нужно еще добавить в эту команду? Догадываюсь, что какая-то лабуда с пайпами или опциями grep, хз.

UPDATE: Я идиод, убейте меня (с) Оно изначально сортирует только по первым двум цифрам. Я просто захотел невозможного, чтобы сортировало «правильно» по датам:

01012023.log:01.01.2023 (time) (login) (etc) IP address (CONNECT)
01022023.log:01.02.2023 (time) (login) (etc) IP address (CONNECT)
01032023.log:01.03.2023 (time) (login) (etc) IP address (CONNECT)
01042023.log:01.04.2023 (time) (login) (etc) IP address (CONNECT)

Такое возможно вообще или нет?

РЕШЕНО:

Либо ugrep -Q -P -F --sort=best -% либо ugrep -Q -P -F --sort=created -% ( удобно для логов, которые были созданы более-менее в эти же даты).

★★★★★

Последнее исправление: Gonzo (всего исправлений: 3)

Честно говоря, это же классически идеальный вопрос для GPT:

Проблема, с которой вы столкнулись, заключается в том, что когда вы начинаете вводить что-то для поиска в fzf, он начинает сортировать результаты исходя из того, как хорошо они соответствуют вашему запросу поиска, а не основываясь на исходной сортировке (которая у вас по датам в именах файлов).

Чтобы сохранить исходный порядок файлов вне зависимости от поискового запроса в fzf, вы можете использовать параметр --no-sort для fzf:

grep -r "" * | fzf --exact --no-sort

Эта опция заставит fzf выводить результаты в том порядке, в котором они поступают на его вход, что, в вашем случае, соответствует сортировке по датам в именах файлов логов.

Однако, учтите, что если grep будет выдавать результаты в неотсортированном порядке (к примеру, если файлы будут обработаны не по порядку), то --no-sort не решит проблему сортировки как таковую. В таком случае, может понадобиться явно отсортировать вывод grep перед передачей его в fzf. Если порядок файлов важен и grep может в некоторых обстоятельствах выводить их не в нужной последовательности, вы можете использовать sort:

grep -r "" * | sort | fzf --exact --no-sort

Тут sort сортирует весь вывод grep по алфавиту (который, благодаря формату ваших имен файлов, совпадает с календарным порядком), а fzf затем показывает результаты в этом порядке, не меняя его при поиске.

Это должно помочь сохранить результаты в нужном порядке независимо от того, что ищется в fzf.

alexmaru
()
Ответ на: комментарий от alexmaru

Тут sort сортирует весь вывод grep по алфавиту (который, благодаря формату ваших имен файлов, совпадает с календарным порядком)

02012023 > 01022023, ага.

chupasaurus
()
Ответ на: комментарий от intelfx

Все перепробовал… Либо не сортирует, либо сортирует, но почему-то по первым двум цифрам:

01042023.log
02012023.log
03022023.log
04012023.log

Главное ж, как только запускаешь команду, все отсортировано как надо. Не могу понять, что ему не так :(

Gonzo ★★★★★
() автор топика
Последнее исправление: Gonzo (всего исправлений: 2)
Ответ на: комментарий от dataman

Попробовал, забавная штука, но сортирует тоже по первым двум цифрам. И еще: как заставить его искать строгую последовательность символов, а не все, что имеются в файлах?

Gonzo ★★★★★
() автор топика
Ответ на: комментарий от Gonzo

Все перепробовал… Либо не сортирует, либо сортирует, но почему-то по первым двум цифрам:

Стоп, ну естественно, я видимо совсем уже не соображал вечером. У тебя порядок алфавитной сортировки не совпадает с хронологическим.

А в самом начале всё отсортировано как надо потому что файлы в каталоге, скорее всего, создавались в хронологическом порядке, и readdir их возвращает в порядке линейного прохода по таблице каталога (у тебя ведь какая-нибудь ext3/4?).

fzf --scheme=history --tiebreak=index --no-sort
intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от intelfx

файлы в каталоге, скорее всего, создавались в хронологическом порядке, и readdir их возвращает в порядке линейного прохода по таблице каталога

Что абсолютно ничего общего с хронологией не имеет (а ловко вы отредактировали).

(у тебя ведь какая-нибудь ext3/4?).

Началось. Можно подумать ваша глубоко любимая btrfs чем то отличается. Я уверен - её развалить мне усилий займёт меньше.

bugfixer ★★★★★
()
Последнее исправление: bugfixer (всего исправлений: 2)
Ответ на: комментарий от intelfx

То же самое. Да, файлы создавались +/- хронологически, но в конце каждого лога есть пару записей уже следующего дня. Соответственно, дата создания лога > даты в имени файла на единицу. Но я не думаю, что это должно влиять, ведь при запуске команды все правильно отсортировано по имени файлов в формате даты.

А потом сортировка ломается и работает только с первыми двумя цифрами.

Gonzo ★★★★★
() автор топика
Ответ на: комментарий от dmitry237

У него нет «наиболее релевантных» (или «наименее релевантных»). Это просто поиск. Развернуть его можно опцией –reverse, но мне не это вовсе нужно.

Gonzo ★★★★★
() автор топика
Ответ на: комментарий от intelfx

Можно у файлов предварительно поменять дату создания на что-то одно. Не вопрос. Лишь бы работала сортировка.

Gonzo ★★★★★
() автор топика
Ответ на: комментарий от Gonzo

Это просто поиск

Вот он и сортирует в порядке лексических соответствий тому, что вы ввели, а не строки в целом.

dmitry237 ★★★
()
Ответ на: комментарий от Gonzo

А теперь перечитай то, что я написал. Если пытаться отсортировать твои строки в алфавитном порядке, как раз и получится «сортировка по первым двум цифрам», которая не совпадает с правильной сортировкой по датам.

А «правильная сортировка по датам» — это просто перечисление файлов в порядке их появления в командной строке grep (после раскрытия *), то есть банально в порядке readdir. Который, скорее всего, и совпадает с хронологическим, потому что твои файлы создавались именно так.


Я только что потестировал на синтетических данных твоего формата. fzf --no-sort работает как ты хочешь. Можешь ещё попробовать fzf --no-sort --reverse, чтобы было заметнее.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от Gonzo

ведь при запуске команды все правильно отсортировано по имени файлов в формате даты.

Сортирует сама ls.

А потом сортировка ломается

Если кто-то активно создаёт файлы, пусть даже хронологически, пусть даже с именами заранее определённого (лексиграфически-хронологически-naturally отсортированного) формата - правильно (atomically, без пропусков) это вычитать занимает определённых усилий. readdir не хватает.

bugfixer ★★★★★
()
Последнее исправление: bugfixer (всего исправлений: 1)
Ответ на: комментарий от Gonzo

Тебе не нужно менять дату создания файлов, она ни при чём.

intelfx ★★★★★
()
Ответ на: комментарий от bugfixer

Есть подозрение, что тебя вопрос btrfs почему-то волнует гораздо сильнее, чем меня. Интересно, с чего бы это.

Что абсолютно ничего общего с хронологией не имеет

Естественно, имеет. Если мы имеем дело с классической ФС, которая хранит directory entries в линейном массиве или эквивалентной структуре, то порядок их перечисления с помощью readdir будет, внезапно, совпадать с порядком их создания (фактического).

Началось. Можно подумать ваша глубоко любимая btrfs чем то отличается

Интересно. Фанатиком ты называешь меня, а помешательство у тебя. При чём тут вообще btrfs? И при чём тут «разваливаемость»?

Но если мы уж заговорили, то да, отличается — банально потому что она всегда хранит directory entries в B-дереве, где ключи этого дерева всегда представляют собой хэши от имён файлов. Поэтому в btrfs порядок перечисления файлов непредсказуем, т. к. readdir тупо идёт по дереву слева направо от lower bound ключей данного каталога до upper bound этого же каталога. А в ext3/4, пока размер каталога не превысит один блок, это не так, и directory entries хранятся линейно в порядке создания. Вот и всё.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 4)
Ответ на: комментарий от bugfixer

Сортирует сама ls

А теперь покажи в треде хотя бы один вызов ls, умник.

intelfx ★★★★★
()
Ответ на: комментарий от intelfx

то порядок их перечисления с помощью readdir будет, внезапно, совпадать с порядком их создания (фактического).

Да что вы говорите. Реально?? Вас много ждёт «открытий чудных».

bugfixer ★★★★★
()
Ответ на: комментарий от dataman

Блин! Это почти то, что мне надо! Но… не могу заставить выборку делать строгую. И да, мне нужна не команда с запросом (как ты предлагаешь), а на лету писать туда запрос. Не могу чет разобраться в его опциях… Вроде -w должна указывать на поиск «только полного слова», но все равно при вводе a34 выбирает a034, а394, а324 и т.д. Ну ты понял.

Gonzo ★★★★★
() автор топика
Ответ на: комментарий от intelfx

Ясно, спасибо большое за уделенное время. Буду разбираться. Тут еще ugrep посоветовали, он мне кажется удобнее, только разберусь со строгим поиском в нем. Вообще ништяк. Благодарю еще раз.

Gonzo ★★★★★
() автор топика
Ответ на: комментарий от Gonzo

Вроде -w должна указывать на поиск «только полного слова»

Тогда нужно убрать -Z: ugrep -Q -w -F -e <строка>

а на лету писать туда запрос

А подробнее?

dataman ★★★★★
()
Ответ на: комментарий от dataman

А подробнее?

Ну он же интерактивный. Я просто запускаю из директории ugrep -Q -Z --sort=best -% и вперед, печатаешь в строке поиска что надо. Но не могу в интерактивном режиме заставить искать строгую последовательность символов, например, ab3.

Gonzo ★★★★★
() автор топика
Последнее исправление: Gonzo (всего исправлений: 1)
Ответ на: комментарий от dataman

Пишет [no matches found], хотя оно там все есть. Хз, почему так. Спрошу еще помощи у чавака на гитхабе.

Gonzo ★★★★★
() автор топика
Ответ на: комментарий от Gonzo

Да, похоже на баг. Я проверял на версии 5.0.

dataman ★★★★★
()

Если это логи, то именовать их надо в соответствии с RFC-3339/ISO-8601, тогда проблем с сортировкой не будет в принципе. Формат DMY (в любых его проявлениях; да-да, @maxcom, почему это моё сообщение датировано 24 февраля 2020 года?) — самая дебильная практика, которую только можно было избрать. Сами себе палок в колёса навставляют, и потом героически с этим борятся…

Если нет возможности изменить именование (на этапе генерации, разумеется) файлов, то стоит сортировать по ctime:

ls -U1 . | xargs -n1 cat | ...
mord0d ★★★★★
()
Последнее исправление: mord0d (всего исправлений: 1)
Ответ на: комментарий от intelfx

Я идиод, убейте меня (с)

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

Мне просто вдруг захотелось невозможного, чтобы сортировало «правильно» по датам, вот так:

01012023.log:01.01.2023 (time) (login) (etc) IP address (CONNECT)
01022023.log:01.02.2023 (time) (login) (etc) IP address (CONNECT)
01032023.log:01.03.2023 (time) (login) (etc) IP address (CONNECT)
01042023.log:01.04.2023 (time) (login) (etc) IP address (CONNECT)

Такое вообще возможно как-то насобачить в баше или прочими grep/awk тулзами или товарищ выше таки прав, что такой формат даты - зло и ССЗБ ?

Gonzo ★★★★★
() автор топика
Последнее исправление: Gonzo (всего исправлений: 3)
Ответ на: комментарий от Gonzo

Такое вообще возможно как-то насобачить в баше или прочими grep/awk

Как вариант натравить на awk поменяв поля местами.

anc ★★★★★
()
Ответ на: комментарий от Gonzo

Добавлю, что в пятую версию добавили ключ --index для поддержки индексов утилиты https://github.com/Genivia/ugrep-indexer, которая рекурсивно создаёт индексы в каждой директории.
Проверил – поиск существенно ускорился.

dataman ★★★★★
()
Ответ на: комментарий от dataman

ugrep мне нравится даже больше, он нагляднее что ли. Осталось только решить проблему строгого поиска (конкретно заданной последовательности) символов.

Gonzo ★★★★★
() автор топика
Ответ на: комментарий от dataman

В Арче оно вроде и так включено. По крайней мере в PKGBUILD такое:

depends=(bzip2
         lz4
         pcre2
         xz
         zlib
         zstd)
Gonzo ★★★★★
() автор топика
Ответ на: комментарий от Gonzo

А там какая версия, пятая?

$ ugrep --version
ugrep 5.0.0 x86_64-pc-linux-gnu +avx2; -P:pcre2jit; -z:zlib,bzip2,lzma,lz4,zstd
License: BSD-3-Clause; ugrep user manual: <https://ugrep.com>
Written by Robert van Engelen and others: <https://github.com/Genivia/ugrep>
Ugrep utilizes the RE/flex regex library: <https://github.com/Genivia/RE-flex>
dataman ★★★★★
()
Последнее исправление: dataman (всего исправлений: 1)
Ответ на: комментарий от dataman

Да, пятая. Не, все нормально! Опция работает и так. Спасибо тебе огромное за подсказки и потраченное на меня время! :)

Gonzo ★★★★★
() автор топика
Ответ на: комментарий от Gonzo

Зачем тебе тут grep? Оно же тупо выплюнет всё как есть, что уже делает cat. В твоём случае достаточно так:

ls -U1 . | xargs -n1 cat | fzf

Даже в изначальном варианте достаточно было сделать просто cat *, ибо grep -r "" * это рекурсивно вывести содержимое файлов (рекурсивно, любой вложенности, но у тебя же плоский список без вложенных директорий?) по пустому паттерну (то есть любое вхождение). Если же у тебя там имеются директории, в которых тоже нужно искать, то тут придётся действовать чуть сложнее, и надёжнее будет использовать find+stat (но это долго/дорого).

Можно написать скрипт, который парсит твои логи и формат в них, но конвертировать из non-RFC3339 больно (на самом деле не очень, но всё равно), потому это останется на тебе. (=

mord0d ★★★★★
()
Ответ на: комментарий от dataman

Просто кое-кому надо иногда читать мануалы… :(

Gonzo ★★★★★
() автор топика
Ответ на: комментарий от Gonzo

таки прав, что такой формат даты - зло и ССЗБ ?

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

mord0d ★★★★★
()
Ответ на: комментарий от dataman

ugrep -Q -P -F --sort=created -%

Вообще песня! Я добился того, чего хотел. Респект и спасибо.

Gonzo ★★★★★
() автор топика
Ответ на: комментарий от intelfx

Блин, туплю. Вот так, конечно же:

01012023.log:01.01.2023 (time) (login) (etc) IP address (CONNECT)
02012023.log:01.02.2023 (time) (login) (etc) IP address (CONNECT)
03012023.log:01.03.2023 (time) (login) (etc) IP address (CONNECT)
04012023.log:01.04.2023 (time) (login) (etc) IP address (CONNECT)

Сначала дни, потом месяцы.

Gonzo ★★★★★
() автор топика
Ответ на: комментарий от intelfx

Это опция грепа? Как сделать, чтобы сначала сортировалось по дням, потом по месяцам? (я тебя, наверное, задолбал уже сегодня, прости)

Gonzo ★★★★★
() автор топика
Ответ на: комментарий от intelfx

то порядок их перечисления с помощью readdir будет, внезапно, совпадать с порядком их создания (фактического).

Да что вы говорите. Реально?? Вас много ждёт «открытий чудных».

Поправлюсь - то что вы сказали возможно будет справедливо только если из директории ничего не удаляли, никогда. Гораздо более интересная (и жизненная) ситуация возникает если у вас имеется producer + consumer, и число актуальных файлов остаётся более-менее константой.

bugfixer ★★★★★
()
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)