Назад | Перейти на главную страницу

Определите количество уникальных строк с помощью awk или аналогичного в bash

Я использую 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

Это не так компактно, как сценарий Тора, но я обычно обнаруживаю, что как только я написал что-то подобное, я хочу сделать больше с самими строками, поэтому я оставил видимый массив (отслеживая количество уникальных линий) там.