У меня огромный файл журнала. Мне нужно что-то найти и распечатать последнюю строку. Как это:

tail -n +1 "$log" | awk '$9 ~ "'$something'" {print $0}' | tail -n1

Но когда я выполняю эту команду, tail начинается с 1-й строки и читает все строки. И бегает несколько минут.

Как я могу начать читать с последней строки и останавливаться, когда что-то найду? Так что, может быть, мне не нужно читать все строки и бегать всего несколько секунд. Потому что мне нужна последняя строчка о $something.

2
onur 1 Дек 2014 в 18:54
Вам нужна последняя строка, содержащая определенное слово? если это так, вы должны объединить grep и tail.
 – 
Reut Sharabani
1 Дек 2014 в 18:56
Да, мне нужно напечатать только последнюю строку о чем-то $. Но не читая всех строк.
 – 
onur
1 Дек 2014 в 18:57
2
Обратите внимание на разницу между tail -n+X (печать из строки X) и tail -X / tail -nX (конец X последних строк).
 – 
fedorqui
1 Дек 2014 в 19:01

4 ответа

Лучший ответ

Обратите внимание, что вы говорите tail -n +1 "$log", что интерпретируется tail как: начать чтение со строки 1. Значит, вы на самом деле делаете cat "$log".

Вероятно, вы захотите сказать tail -n 1 "$log" (без + перед 1), чтобы получить последние строки n.

Кроме того, если вы хотите получить последнее совпадение $something, вы можете использовать tac. Это печатает файл в обратном порядке: сначала последняя строка, затем предпоследняя ... и, наконец, первая.

Итак, если вы это сделаете

tac "$log" | grep -m1 "$something"

Это напечатает последнее совпадение $something, а затем выйдет, потому что -mX печатает первые совпадения X.

Или, конечно, вы также можете использовать awk:

tac "$log" | awk -v pattern="$something" '$9 ~ pattern {print; exit}'

Обратите внимание на использование -v для передачи переменной awk. Таким образом вы избегаете запутанного смешения одинарных и двойных кавычек в вашем коде.

4
fedorqui 1 Дек 2014 в 19:15
Спасибо, это работа для меня. Могу ли я использовать более 1 шаблона? Например, если ~ что-то и что-то2, напечатайте.
 – 
onur
3 Дек 2014 в 18:25
1
Конечно, вы можете сказать, например: awk -v pattern="$something" '$9 ~ pattern && $7==7 {print; exit}'. Обратите внимание на &&, чтобы ввести другое условие, если вы хотите, чтобы оба условия были выполнены. Если это ИЛИ, используйте ||.
 – 
fedorqui
3 Дек 2014 в 19:03

tac $FILE | grep $SOMETHING -m 1

tac: обратная сторона cat :-)

grep -m: искать и останавливать при первом появлении

2
Reut Sharabani 1 Дек 2014 в 19:04

Вместо tail используйте tac. Он перевернет файл, и вы можете выйти, когда впервые что-то grep:

tac "$log" | awk '$9 ~ "'$something'" {print $0;exit}'
2
fredtantini 1 Дек 2014 в 19:06
3
Не используйте значения переменных оболочки как часть синтаксиса вашего awk-скрипта, иначе вы можете получить всевозможные ужасные последствия в зависимости от значения этой переменной оболочки. Используйте -v для инициализации переменной awk со значением переменной оболочки.
 – 
Ed Morton
1 Дек 2014 в 20:29

tail -1000 берет только последние 1000 строк из вашего файла. Вы можете использовать grep для этой части, но вы не узнаете, произошло ли то, что вы ищете, в предыдущих строках. Нет возможности использовать grep «назад».

1
geert3 1 Дек 2014 в 19:01