Получение последнего совпадения в файле с использованием grep

58

Каков наилучший способ получить только окончательное совпадение регулярного выражения в файле с использованием grep?

Кроме того, возможно ли начать поиск с конца файла вместо начала и остановить, когда он найдет первое совпадение?

Желудь
источник

Ответы:

85

Вы могли бы попробовать

grep pattern file | tail -1

или же

tac file | grep pattern | head -1

или же

tac file | grep -m1 pattern
Cakemox
источник
20
tac file | grep -m 1 pattern
Деннис Уильямсон
1
С добавленным ограничением, что я хотел получить номер строки ( grep -n) в реальном файле, я думаю, что в tacзначительной степени нужно было избегать, если только я не хотел делать некоторое вычитание с wc -l. В противном случае tacс grep -m1делает много смысла.
Ник Меррилл
1
Я хотел бы видеть более производительную версию, чем эта, так как я пытаюсь найти файл размером 20 ГБ.
Джефф
Ответ @DennisWilliamson намного лучше, потому grepчто перестанет работать после первого матча. без -m 1, grepсначала найдет все подходящие шаблоны в файле , затем headпокажет только первый - гораздо менее эффективный. Денис, рассмотрите возможность размещения этого в отдельном ответе!
Гилад Майани
1

Для тех, кто работает с огромными текстовыми файлами в Unix / Linux / Mac / Cygwin. Если вы используете Windows, проверьте это об инструментах Linux в Windows: https://stackoverflow.com/questions/3519738/what-is-the-best-way-to-use-linux-utilities-under-windows .

Можно следовать этому рабочему процессу, чтобы иметь хорошую производительность:

  1. сжать с помощью gzip
  2. используйте zindex (на github: https://github.com/mattgodbolt/zindex ), чтобы проиндексировать файл с соответствующим ключом
  3. запросить индексированный файл zqиз пакета.

Цитата из его github readme:

Создание индекса

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

По умолчанию zindex создает индекс file.gz.zindex, когда его просят проиндексировать file.gz.

Пример:

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

$ zindex file.gz --regex 'id:([0-9]+)' --numeric --unique

Пример: создайте индекс во втором поле файла CSV:

$ zindex file.gz --delimiter , --field 2 

Пример:

создайте индекс для поля JSON orderId.id в любом из элементов в массиве действий корня документа (требуется jq). Запрос jq создает массив всех orderId.ids, а затем соединяет их пробелом, чтобы каждая отдельная строка, переданная в jq, создавала одну строку вывода с несколькими совпадениями, разделенными пробелами (это разделитель по умолчанию).

$ zindex file.gz --pipe "jq --raw-output --unbuffered '[.actions[].orderId.id] | join(\" \")'" 

Запрос индекса

Программа zq используется для запроса индекса. Ему дается имя сжатого файла и список запросов. Например:

$ zq file.gz 1023 4443 554 

Также возможно вывести по номеру строки, чтобы вывести строки 1 и 1000 из файла:

$ zq file.gz --line 1 1000
biocyberman
источник
1

Я всегда использую cat (но это делает его немного длиннее): cat file | grep pattern | tail -1

Я бы обвинил моего преподавателя курса администратора Linux в колледже, который любит кошек :))))

- Вам не нужно сначала следить за файлом, прежде чем искать его. grep pattern file | tail -1и более эффективен тоже.

Исмаил Гунейдас
источник
6
Это только первая часть ответа Cakemox, кроме худшего.
augurar
Это работает, но это делает ненужные шаги. Для легкого использования это решение работает хорошо, но оно не работает хорошо. Причина в том, что вам не нужен catфайл и канал к нему grep. Вы можете grepискать файл напрямую через grep pattern file(и затем использовать tailдля возврата последнего результата), как в ответе Cakemox.
29