Bash Script: подсчет уникальных строк в файле

129

Ситуация:

У меня есть большой файл (миллионы строк), содержащий IP-адреса и порты из нескольких часов сетевого захвата, по одному IP / порту на строку. Строки имеют следующий формат:

ip.ad.dre.ss[:port]

Желаемый результат:

Есть запись для каждого пакета, который я получил во время регистрации, поэтому существует много повторяющихся адресов. Я хотел бы иметь возможность запускать это через какой-то сценарий оболочки, который сможет сократить его до строк формата

ip.ad.dre.ss[:port] count

где count- количество появлений этого конкретного адреса (и порта). Никакой особой работы не требуется, относитесь к разным портам как к разным адресам.

Пока что я использую эту команду для очистки всех IP-адресов из файла журнала:

grep -o -E [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+(:[0-9]+)? ip_traffic-1.log > ips.txt

Из этого я могу использовать довольно простое регулярное выражение, чтобы очистить все IP-адреса, которые были отправлены с моего адреса (что меня не волнует)

Затем я могу использовать следующее для извлечения уникальных записей:

sort -u ips.txt > intermediate.txt

Я не знаю, как я могу каким-то образом агрегировать количество строк с помощью sort.

ГВП
источник

Ответы:

303

Вы можете использовать uniqкоманду для получения количества отсортированных повторяющихся строк:

sort ips.txt | uniq -c

Чтобы получать наиболее частые результаты наверху (спасибо Питеру Ярику):

sort ips.txt | uniq -c | sort -bgr
Майкл Хоффман
источник
10
Мне нравится, как по -bgrсовпадению выглядит мнемоника для bigger, чего мы и хотим наверху.
dwanderson
1
В качестве небольшой функции для вашего .bashrcили .bash_aliasesфайла: function countuniquelines () { sort "$1" | uniq -c | sort -bgr; }. Позвоните через countuniquelines myfile.txt.
Johan
Не знаю, почему бы и нет sort -nr.
Накилон
5

Чтобы подсчитать общее количество уникальных строк (т.е. без учета повторяющихся строк), мы можем использовать uniqили Awk с wc:

sort ips.txt | uniq | wc -l
awk '!seen[$0]++' ips.txt | wc -l

Массивы AWK ассоциативны, поэтому он может работать немного быстрее, чем сортировка.

Создание текстового файла:

$  for i in {1..100000}; do echo $RANDOM; done > random.txt
$ time sort random.txt | uniq | wc -l
31175

real    0m1.193s
user    0m0.701s
sys     0m0.388s

$ time awk '!seen[$0]++' random.txt | wc -l
31175

real    0m0.675s
user    0m0.108s
sys     0m0.171s
qwr
источник
Интересный. Может иметь большое значение для огромных наборов данных
Вуг
1

Это самый быстрый способ подсчитать количество повторяющихся строк и красиво их распечатать, перейдя от наименее частых к наиболее частым:

awk '{!seen[$0]++}END{for (i in seen) print seen[i], i}' ips.txt | sort -n

Если вас не волнует производительность и вы хотите что-то более легкое для запоминания, просто запустите:

sort ips.txt | uniq -c | sort -n

PS:

sort -n анализирует поле как число, это правильно, поскольку мы выполняем сортировку по счетчикам.

Лука Мастростефано
источник
Здесь !in {!seen[$0]++}является избыточным, поскольку мы печатаем только в END.
Амир