У меня есть файл с 30 000 000 строк (учет радиуса), и мне нужно найти последнее совпадение данного шаблона.
Команда:
tac accounting.log | grep $pattern
дает то, что мне нужно, но это слишком медленно, потому что ОС должна сначала прочитать весь файл, а затем отправить в канал.
Итак, мне нужно что-то быстрое, что может прочитать файл с последней строки до первой.
источник
tac
, моя точка зрения заключалась в том, что это не поможет, если вы также не используете,-m
так как файл все еще должен быть полностью прочитан двумя программами. В противном случае вы можете просто найти все события и оставить только последний, как яtail -n 1
.grep -m
этим он должен быть достаточно эффективным.grep -m
этим есть. OP не использовал,-m
поэтому grep и tac обрабатывали все это.awk
строки?Причина по которой
не останавливается на первом матче из-за буферизации.
Обычно
head -n 1
выходит после прочтения строки. Поэтомуgrep
следует получить SIGPIPE и завершить работу, как только он напишет вторую строку.Но что происходит, так это потому, что его вывод не идет в терминал,
grep
буферизует его. То есть он не пишет его, пока не накопит достаточно (4096 байт в моем тесте с GNU grep).Это означает, что
grep
он не завершится до того, как записал 8192 байта данных, так что, вероятно, довольно много строк.С GNU
grep
вы можете сделать так, чтобы он выходил быстрее, используя команду,--line-buffered
которая говорит ему писать строки, как только они найдены, независимо от того, идет ли к терминалу или нет. Такgrep
что тогда выходил бы на второй строке, которую он находит.Но с GNU в
grep
любом случае вы можете использовать-m 1
вместо этого, как показало @terdon, что лучше, когда он выходит при первом совпадении.Если ваш
grep
не GNUgrep
, то вы можете использоватьsed
илиawk
вместо. Но,tac
будучи командой GNU, я сомневаюсь, что вы найдете систему, вtac
которойgrep
нет GNUgrep
.Некоторые системы должны
tail -r
делать то же самое, что и GNUtac
.Обратите внимание , что для регулярных (доступных для поиска) файлов,
tac
иtail -r
являются эффективными , потому что они делают читать файлы назад, они не просто чтение файла полностью в памяти перед печатью назад (как @ ОДС это СЭД подхода илиtac
на нерегулярных файлах будет) ,В системах, где ни нет,
tac
ниtail -r
доступно, единственные варианты - реализовать обратное чтение вручную с помощью языков программирования, таких какperl
или использующих:Или:
Но это значит найти все совпадения и напечатать только последний.
источник
Вот возможное решение, которое найдет местоположение первого появления шаблона из последнего:
Это использует
-s
и-r
переключатели,tac
которые являются следующими:источник
Используя sed
Показаны некоторые альтернативные методы для точного ответа @ Terdon, используя
sed
:Примеры
Использование Perl
В качестве бонуса, немного более простую запись в Perl:
пример
источник
sed
тот), вероятно, будет на несколько порядков медленнее, чемgrep 5 | tail -n1
илиsed '/5/h;$!d;g'
. Это также потенциально будет использовать много памяти. Это не намного более портативно, так как вы все еще используете GNUgrep -m
.