Печатать только уникальные строки, которые появляются последними в файле журнала на основе даты / времени

в зависимости от вашего дистрибутива, он должен быть расположен в /var/lib/dhcp под dhclient.{interface}.leases или /var/lib/dhclient.leases. вы также можете указать путь к файлу dhclient.leases, передав -lf при запуске dhclient.

3
04.11.2016, 00:59
4 ответа

Если вы собираетесь делать второй проход (что, в общем-то, необходимо), вы можете хранить только номера строк, а не полные записи. Это упрощает логику.

awk 'NR == FNR {if (z[$6]) y[z[$6]]; z[$6] = FNR; next} !(FNR in y)' logfile logfile

Доказательство корректности:

В конце обработки каждой строки, номер каждой обработанной строки является либо значением в z, либо индексом (не значением) в y, но никогда не обоими.

Строки, представленные значениями в z, в конце каждой итерации являются точно и только последними записями, которые до сих пор были замечены для каждого IP-адреса.

Индексы в y - это, следовательно, именно те строки, которые мы хотим не напечатать.

5
27.01.2020, 21:09

Сохранить всю строку (используя $ 6 в качестве индекса массива) и в END перебрать элементы array:

awk '{z[$6]=$0};END{for (i in z) print z[i]}' logfile

Однако результат не будет отсортирован ... Вы можете сделать что-то вроде:

awk '{z[$6]=NR" "$0};END{for (i in z) print z[i]}' logfile | sort -k1,1n | cut -f2-
### this space ^ is a literal TAB

, что сохранит номер строки. плюс содержимое строки, чтобы затем можно было отсортировать по номеру строки.


Другие способы включают второй проход для сортировки по дате (так как это журнал), но будут печатать повторяющиеся записи, если входные данные содержат повторяющиеся строки (то есть целые строки) - например, с grep :

awk '{z[$6]=$0};END{for (var in z) print z[var]}' logfile | grep -Fxf- logfile

или только с awk :

awk 'NR==FNR{z[$6]=$0;next}
FNR==1{for (var in z) y[z[var]]}
$0 in y' logfile logfile
3
27.01.2020, 21:09

Если у вас есть строки только за один день, вы можете сделать это следующим образом:

sort -k6 -k3r logfile | uniq -f3 | sort -k3

Если у вас есть строки за несколько дней, вы можете использовать этот базовый подход, но ваша сортировка должна быть гораздо более сложной. Приведенная выше команда может обрабатывать записи только за один день, поскольку она использует часть временной метки (например, 02:28:26) как прокси для всей временной метки.

2
27.01.2020, 21:09

Логика упрощается, если перевернуть файл построчно

$ tac logfile | awk '!seen[$6]++' | tac
Oct 12 02:28:26 server program: 192.168.1.105 text for 1.105 
Oct 12 02:30:00 server program: 192.168.1.104 text for 1.104
Oct 12 02:30:23 server program: 192.168.1.103 text for 1.103 
Oct 12 02:32:39 server program: 192.168.1.101 text for 1.101 
2
27.01.2020, 21:09

Теги

Похожие вопросы