Получить последнюю строку из поиска grep в нескольких файлах

У меня есть проблема с командой grep.

Я нашел способ показать только последнюю строку поиска grep:

grep PATERN FILE_NAME | tail -1

Я также нашел способ сделать поиск grep в нескольких выбранных файлах:

find . -name "FILE_NAME" | xargs -I name grep PATERN name

Теперь я хотел бы получить только последнюю строку результата grep для каждого отдельного файла. Я пробовал это:

 find . -name "FILE_NAME" | xargs -I name grep PATERN name | tail -1

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

Ответ 1

for f in $(find . -name "FILE_NAME"); do grep PATERN $f | tail -1; done

Ответ 2

Как насчет этого хорошего сэр

find . -name "FILE_NAME" -print0 | while read -d '' aa
do
  grep PATTERN "$aa" | tail -1
done

Ответ 3

вы также можете использовать команду find для выполнения команд:

find . -name "<file-name-to-find>" -exec grep "<pattern-to-match>" "{}" ";" | tail -1

"{}" - это имя файла, позаботьтесь о глобализации оболочки и обходе при написании команды

Ответ 4

Вы можете начать с параметра grep -B (before). Например, чтобы получить 5 строк до матча:

[email protected] /etc/php5/apache2 $ grep -i -B5 timezone php.ini 
[CLI Server]
; Whether the CLI web server uses ANSI color coding in its terminal output.
cli_server.color = On

[Date]
; Defines the default timezone used by the date functions
; http://php.net/date.timezone
;date.timezone =

Ответ 5

Получить последнюю строку каждого файла (с префиксом имени файла). Затем отфильтруйте вывод на основе шаблона.

find . -name "*" -exec tail -v -n1 {} \; | grep "some_string" -B1

на MacOS, вы должны сделать это немного по-другому

find . -name "*" | xargs tail -1 | grep "some_string" -B1

Ответ 6

Альтернативой этому может быть использование awk вместо grep. Версия Posix гласит:

awk '(FNR==1)&&s{print s; s=""}/PATTERN/{s=$0}END{if(s) print s}' file1 file2 file3 ...

Используя GNU awk, вы можете использовать ENDFILE

awk 'BEGINFILE{s=""}/PATTERN/{s=$0}ENDFILE{if(s) print s}' file1 file2 file3 ...

Ответ 7

Существует решение без необходимости в циклах, это дает то, что хочет OP.

find . -type f -exec sh -c "fgrep print {} /dev/null |tail -1" \;

./tway.pl:print map(lambda x : x[1], filter(lambda x : x[0].startswith('volume'), globals().items()))
./txml.py:           print("%s does not exist: %s\n" % (host, error))
./utils.py:print combine_dicts(a, b, operator.mul)
./xml_example.py:print ET.tostring(root, method="text")

Сравнено без tail -1 дает Слишком много строк для каждого файла, но доказывает вышеописанные работы.

find . -type f -exec sh -c "fgrep print {} /dev/null" \;

дает:

./tway.pl:print map(lambda x : x[1], filter(lambda x : x[0].startswith('volume'), globals().items()))
./txml.py:           print("%s resolved to --> %s\n" % (host, ip))
./txml.py:           print("%s does not exist: %s\n" % (host, error))
./utils.py:print "a", a
./utils.py:print "b", b
./utils.py:print combine_dicts(a, b, operator.mul)
./xml_example.py:    print ">>"
./xml_example.py:    print ET.tostring(e, method="text")
./xml_example.py:    print "<<"
./xml_example.py:print ET.tostring(root, method="text")

EDIT - удалите /dev/null, если вы не хотите, чтобы имя файла включалось в выход.

Ответ 8

Другой способ найти последнюю строку - это перевернуть файл и вывести первое совпадение.

find . -name "FILE_NAME" | xargs -I name sh -c 'tac name|sed -n "/PATTERN/{p;q}"'

Ответ 9

Самый быстрый способ сделать это - получить последние 1 (или более) строки из файлов, а затем grep через это. Итак -

tail -1 filenames.* | grep "what you want to grep for"