Сортировка и подсчет количества появлений строк

145

У меня есть Apacheлог-файл, access.logкак посчитать количество вхождений строк в этом файле? например , результатом cut -f 7 -d ' ' | cut -d '?' -f 1 | tr '[:upper:]' '[:lower:]'является

a.php
b.php
a.php
c.php
d.php
b.php
a.php

результат, который я хочу, это:

3 a.php
2 b.php
1 d.php # order doesn't matter
1 c.php 
Kokizzu
источник
25
| sort | uniq -c
Костас
3
| LC_ALL=C sort | LC_ALL=C uniq -c
Стефан Шазелас
ах, я никогда не знаю, что uniqможет сделать это ..
Kokizzu
У вас есть пример строки в журнале, так как я думаю, что все это можно сделать с помощью awk без всех каналов.
все в порядке, файл журнала 8,1 ГБ обрабатывается примерно за 2 минуты, и на данный момент все готово, больше это не нужно: 3
Kokizzu

Ответы:

197
| sort | uniq -c

Как указано в комментариях.

Конвейер вывода в sortупорядочивает вывод в алфавитном / числовом порядке.

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

a
b
a

Если вы используете uniqэтот текстовый файл, он вернет следующее:

a
b
a

Это потому, что два as разделены b- они не являются последовательными строками. Однако, если вы сначала отсортируете данные в алфавитном порядке, сначала как

a
a
b

Затем uniqудалите повторяющиеся строки. -cВариант uniqподсчета числа копий и обеспечивает вывод в виде:

2 a
1 b

Рекомендации:

visudo
источник
1
Добро пожаловать в Unix и Linux :) Не стесняйтесь добавлять больше подробностей к вашему ответу и объясните, почему и как это работает;)
Джон У. Смит,
1
printf '%s\n' ①.php ②.php | sort | uniq -cдает мне2 ①.php
Стефан Chazelas
@ StéphaneChazelas Это потому, что printf печатаетphp\nphp
4
@ Джиддер, нет, потому что ①.phpсортирует так же, как ②.phpв моей локали, потому что порядок сортировки для тех и символов в моей локали не определен. Если вы хотите уникальные значения для всех значений байта (помните пути к файлам не обязательно текст), то вам необходимо исправить локаль C: | LC_ALL=C sort | LC_ALL=C uniq -c.
Стефан Шазелас
2
Чтобы отсортировать полученный файл подсчета, вы должны рассмотреть возможность добавления «sort -nr» в виде ответов @ eduard-florinescu ниже.
Луис Суньол
104
[your command] | sort | uniq -c | sort -nr

Принятый ответ почти завершен, вам может понадобиться добавить лишний sort -nrв конце, чтобы отсортировать результаты по наиболее часто встречающимся строкам.

уникальные опции:

-c, --count
       prefix lines by the number of occurrences

варианты сортировки :

-n, --numeric-sort
       compare according to string numerical value
-r, --reverse
       reverse the result of comparisons

В конкретном случае, если строки, которые вы сортируете, являются числами, вам нужно использовать sort -grвместо sort -nr, см. Комментарий

Эдуард Флоринеску
источник
3
Большое спасибо, что сообщили мне о -nварианте.
Сигур
2
Великий ответ, вот что я использую , чтобы получить WordCount из файла с предложениями: tr ' ' '\n' < $FILE | sort | uniq -c | sort -nr > wordcount.txt. Первая команда заменяет пробелы символами новой строки, что позволяет остальной части команды работать как положено.
Бар
2
Используя опции выше, я получаю «1» перед «23344». Использование sort -grвместо этого решает это. -g: сравнить по общему числовому значению (вместо -n: сравнить по числовому значению строки).
Питер Ярич
@PeterJaric Отличный улов, о котором очень полезно знать, -grно я думаю, что результат uniq -cбудет таким, который sort -nrбудет работать так, как задумано
Эдуард Флоринеску
3
На самом деле, когда данные являются числами, -grработает лучше. Попробуйте эти два примера, отличающиеся только флагами g и n: echo "1 11 1 2" | tr ' ' '\n' | sort | uniq -c | sort -nrи echo "1 11 1 2" | tr ' ' '\n' | sort | uniq -c | sort -gr. Первый сортирует неправильно, но не второй.
Питер Ярич
9

Вы можете использовать ассоциативный массив в awk, а затем -optionally- sort :

cat access.log  | awk ' { tot[$0]++ } END { for (i in tot) print tot[i],i } ' | sort

выход:

1 c.php
1 d.php
2 b.php
3 a.php
Лоуренс Р. Угалде
источник
Как бы вы посчитали количество случаев, когда канал отправляет данные?
user123456