Я использовал утилиту хвоста с опцией -f, чтобы посмотреть один из моих файлов журнала. Моя программа CGI всегда отправляла на мою веб-страницу только последние 40 строк файла журнала, где я могу отслеживать журнал в реальном времени и слышимые уведомления. Теперь я хотел бы отправить только последние 40 строк, которые удовлетворяют некоторым условиям, например. соответствует любому шаблону. Я думаю, что мне нужно использовать grep, но как я могу выбрать только последние 40 совпадающих строк? Должен ли я дважды использовать «хвост»?Удаляет ли unix-утилиту весь файл?
ответ
tac file | grep "your regexp here" | head -40 | tac
time (grep bar file | tail -40) >/dev/null
real 0m15.472s
user 0m15.316s
sys 0m0.172s
time (tac file | grep bar | head -40 | tac) >/dev/null
real 0m0.146s
user 0m0.184s
sys 0m0.004s
time (tac file | grep -m40 bar | tac) >/dev/null
real 0m0.005s
user 0m0.000s
sys 0m0.000s
Обнаруженного псевдоним grep="grep -P"
, так что чистые результаты GREP:
time ("grep" bar file | tail -40) >/dev/null
real 0m1.316s
user 0m1.164s
sys 0m0.172s
time (tac file | "grep" bar | head -40 | tac) >/dev/null
real 0m0.071s
user 0m0.040s
sys 0m0.092s
time (tac file | "grep" -m40 bar | tac) >/dev/null
real 0m0.042s
user 0m0.004s
sys 0m0.056s
grep condition file | tail -40
Если это не то, что вы хотите, а затем изменить свой вопрос, чтобы показать некоторые входные выборки и ожидаемые результаты (не 40+ линии на сумму, хотя).
WRT обсуждение производительности в комментариях под https://stackoverflow.com/a/31220727/1745001: На линии файл 1M, где «бар» появляется в 1000 раз, а все остальные строки просто «Foo», как создатель этого сценария:
awk 'BEGIN{for (i=1;i<=1000000;i++) print (i%1000 ? "foo" : "bar")}' > file
Вот третьего запуска синхронизации в Баш 4.3.33 под Cygwin:
$ time (grep bar file | tail -40) >/dev/null
real 0m0.050s
user 0m0.030s
sys 0m0.045s
$ time (tac file | grep bar | head -40 | tac) >/dev/null
real 0m0.100s
user 0m0.061s
sys 0m0.107s
$ time (tac file | grep -m 40 bar | tac) >/dev/null
real 0m0.080s
user 0m0.000s
sys 0m0.090s
на 100M файл создан:
awk 'BEGIN{for (i=1;i<=100000000;i++) print (i%1000 ? "foo" : "bar")}' > file
я получаю:
$ time (grep bar file | tail -40) >/dev/null
real 0m1.014s
user 0m0.841s
sys 0m0.202s
$ time (tac file | grep bar | head -40 | tac) >/dev/null
real 0m1.154s
user 0m1.262s
sys 0m0.248s
$ time (tac file | grep -m 40 bar | tac) >/dev/null
real 0m0.078s
user 0m0.015s
sys 0m0.046s
Все точно так, как ожидалось. Для первых 2 grep выполняет точно такую же обработку при поиске всего файла, а именно то, что приводит к большей длительности, с той лишь разницей в рабочей нагрузке, что tail
против tac+pipe+head+pipe+tac
, тогда как с 3-м, grep делает гораздо меньше работы поскольку он выходит после 40-го матча, и поэтому общий конвейер работает быстрее.
Когда я воспроизвожу свой эксперимент, я получаю одинаковое число на обоих Grep и хвост против ноликов и Grep & головы и ноликов. Но когда я применяю это к реальным данным, способ намного быстрее. Может быть, сгенерированный файл недостаточно велик? –
Добавлено три нуля для сценария генерации awk и значительно улучшена производительность tac –
Вы уверены, что в скобки скопированы аргументы времени, поэтому время для всего конвейера? Когда вы запускаете время по необработанному конвейеру, результаты не уточняются, поэтому ваши результаты могут сравнивать время «tac file» и «grep bar file» вместо сравнения всех конвейеров. –
Вам не хватает дополнительных '| tac' в конце, чтобы вернуть строки в исходный порядок, и единственный способ для этого сделать любой смысл - если вы замените 'grep 'ваше regexp здесь» | head -40' с 'grep -m 40" ваше regexp здесь ", поэтому grep не нужно будет искать весь файл, но вы все равно добавляете' tac' всего файла и 'tac' из 40 строк в конце так idk, если бы он действовал, улучшив производительность над 'grep .. | tail'. –
Изменить 'cat file | grep 1000' в 'grep 1000 файлов'. Вам НИКОГДА не нужно использовать 'cat', чтобы открыть файл для другого инструмента - google UUOC. Вы не говорите, как большой файл или много раз «1000». Кроме того, вы запускали каждую команду 3 раза, прежде чем собирать статистику, чтобы удалить проблемы с кешированием? Если во входном файле часто появляется '1000', а входной файл большой, вы должны увидеть значительное улучшение производительности' grep -m 40 1000 file' vs 'grep 1000 file | head -40'. –
Я знаю о проблеме кеширования, поэтому я попробовал три раза, да. –