У меня есть файл, содержащий два значения ключевого слова initial...
. Я хочу получить последнюю дату для сопоставления строки initial...
. После получения даты мне также нужно отформатировать дату, заменив /
на -
.
---other data
INFO | abc 1 | 2018/01/04 20:04:35 | initial...
INFO | abc 1 | 2018/02/05 17:01:42 | INFO | new| InitialLauncher | c.t.s.s.setup.launch | initial...
---other data
В приведенном выше примере мой вывод должен быть 2018-02-05
. Здесь я беру строку, содержащую значение initial...
, и получаю только строку с последним значением даты. Затем мне нужно вырезать оставшуюся строку и получить только значение даты.
Я использую следующий grep
, но он еще не соответствует требованиям.
grep -q -iF "initial..." /tmp/file.log
У нас всегда будет более новая дата внизу
что-то вроде этого...
$ awk -F'|' '$NF~/initial\.\.\./ {if (max<$3) max=$3}
END {gsub("/","-",max);
split(max,dt," "); print dt[1]}' file
Я получаю нулевое значение. также пробовал заменить initial
на initial\.\.\.
лишнее место в ФС. Также sub-> gsub попробуйте сейчас.
Возможно, сначала разделить, а потом заменить, но мне уже поздно это менять.
Grep для только (-o
) нужной строки, отсортируйте ее и вырежьте для первого слова:
grep -o '2[0-9]\{3\}/[0-9][0-9]/[0-9][0-9] [0-2][0-9]:[0-5][0-9]:[0-9][0-9] .* | initial' file.txt | sort | cut -d' ' -f1 | tai -1
Это дает первое значение 2018/01/04
. Однако правильным выходом должен быть 2018/02/05
. Мне также нужно изменить форматирование и выводить как 2018-02-05
Просто добавил еще один подстановочный знак. Не знал, какая у вас целевая строка. (Конечно, вы могли бы зайти так далеко в одиночку, да?)
Я сделал это пока что grep -iF "initial..." file.txt | tail -n 1 | grep -o '2[0-9]\{3\}/[0-9][0-9]/[0-9][0-9] [0-2][0-9]:[0-5][0-9]:[0-9][0-9]'
Я потерял хвост! Я чувствую себя Иа-Ё.
Зная, что более поздние даты появляются позже в файле, необходимо только распечатать дату из последней строки, содержащей initial...
.
Первый шаг (отбросьте -q
от grep
- вы не хотите, чтобы он был тихим):
grep -iF 'initial...' /tmp/file.log |
tail -n 1 |
sed -e 's/^[^|]*|[^|]*| *\([^ ]*\) .*/\1/' -e 's%/%-%g'
(Первая) команда s///
сопоставляет серию не-каналов, за которыми следует канал, другая серия не-каналов, за которыми следует канал, пробел, затем захватывает серию непустых значений и, наконец, сопоставляет пробел и все что угодно; он заменяет все это только захваченной строкой, которая является полем даты после второй вертикальной черты в строке ввода. (Вторая) команда s%%%
заменяет косую черту на тире, используя %
, чтобы избежать путаницы, которую может вызвать эквивалентный s///-/g
, тем самым переформатируя дату в формате в стиле ISO 8601.
Но мы можем потерять tail
с:
grep -iF 'initial...' /tmp/file.log |
sed -n -e '$ { s/^[^|]*|[^|]*| *\([^ ]*\) .*/\1/; s%/%-%gp; }'
-n
подавляет нормальный вывод; $
соответствует только последней строке; p
после второй операции s///
распечатывает результат.
Поиск с фиксированным шаблоном без учета регистра более удобен в grep
, чем в sed
. Хотя это можно сделать с помощью одной команды sed
, вам придется потрудиться довольно много, сохраняя совпадающие строки в удерживаемом пространстве, затем поменяв местами удержание и пространство шаблона в конце и выполняя замену и печать:
sed -n \
-e '/[Ii][Nn][Ii][Tt][Ii][Aa][Ll]\.\.\./h' \
-e '$ { x; s/^[^|]*|[^|]*| *\([^ ]*\) .*/\1/; s%/%-%gp; }' /tmp/file.log
Каждый из них дает результат 2018-02-05 на основе выборочных данных. Если на входе нет initial...
, они ничего не выводят.
Будут ли данные когда-либо храниться с более новой датой перед более старой датой? Если нет, вы можете просто запустить вывод от
grep
доtail -n 1
, чтобы получить последнюю строку, и продолжить оттуда.