Я использую AWK для чтения пользовательского файла журнала, который у меня есть. Формат примерно такой:
[12:08:00 +0000] 192.168.2.3 98374 "CONNECT 192.168.2.4:8091 HTTP/1.0" 200
Прямо сейчас у меня AWK (из bash) настроен на чтение всего журнала, анализ каждой строки и захват каждой строки, содержащей «CONNECT», который работает, однако это не помогает мне обнаруживать уникальных клиентов.
Для этого можно как-то отфильтровать его, чтобы он анализировал эту часть каждой строки: «CONNECT 192.168.2.4:8091 HTTP / 1.0»
Если бы существовал способ получить все эти строки в файле журнала, сравните их все и считайте только похожие строки как одну. Так скажем, например:
[12:08:00 +0000] 192.168.2.3 98374 "CONNECT 192.168.2.6:8091 HTTP/2.0" 200
[12:08:00 +0000] 192.168.2.3 98374 "CONNECT 192.168.2.9:8091 HTTP/2.0" 200
[12:08:00 +0000] 192.168.2.3 98374 "CONNECT 192.168.2.2:8091 HTTP/2.0" 200
[12:08:00 +0000] 192.168.2.3 98374 "CONNECT 192.168.2.9:8091 HTTP/2.0" 200
В этом случае мне нужен ответ 3, а не 4. Поскольку 2 строки одинаковы, то есть только 3 уникальные строки. Мне нужен автоматический способ сделать это с помощью AWK.
Было бы здорово, если бы кто-нибудь протянул руку помощи.
sed -re 's/.*"([^"]*)".*/\1/' <logfile> |sort |uniq
Вариант awk: awk -F'"' {print $2} <logfile> |sort |uniq
Добавить -c
к uniq
чтобы получить количество каждой совпадающей строки, или |wc -l
чтобы подсчитать количество совпадающих строк.
Вы можете позволить awk подсчитывать уникальные экземпляры следующим образом:
awk -F\" '/CONNECT/ && !seen[$2] { seen[$2]++ } END { print length(seen) }' logfile
Вывод:
3
Это собирает первую строку в двойных кавычках из строк, содержащих CONNECT
в seen
хэш-массив. Когда достигается конец ввода, количество элементов в seen
печатается.
Запуск файла журнала через сортировку | uniq должен отфильтровать повторяющиеся строки, но я бы спросил, почему у вас там эти строки. Они действительно дубликаты?
Если это допустимые записи журнала и все, что вам нужно, это уникальный список клиентов (второе поле) для строк, которые не являются дубликатами, тогда простая модификация сценария @ Thor должна дать вам то, что вы хотите:
awk '
/CONNECT/ {
if (seen[$0] == 0) {
clients[$3]++
}
seen[$0]++
}
END {
for (i in clients) {
print i
}
}'
Что для приведенного вами образца приводит к:
192.168.2.3
Это не так компактно, как сценарий Тора, но я обычно обнаруживаю, что как только я написал что-то подобное, я хочу сделать больше с самими строками, поэтому я оставил видимый массив (отслеживая количество уникальных линий) там.