open atlas
↑ К треку
Командная строка CLI · 06 · 02

sort и uniq

sort упорядочивает строки лексически или численно; -k выбирает ключ сортировки по полю, -n сортирует численно, -r разворачивает. uniq -c подсчитывает последовательные одинаковые строки. Идиома sort | uniq -c | sort -rn строит таблицу частот от большего к меньшему.

CLI Middle ◷ 22 min
Уровень
ОсновыJuniorMiddleSenior

У тебя есть лог-файл с тысячами строк. Какой IP-адрес сделал больше всего запросов? Какой HTTP-код чаще всего встречается? Что входит в топ-10 эндпоинтов по числу обращений? Это вопросы частоты, и ответ — трёхэтапный конвейер: sort | uniq -c | sort -rn. Эта идиома работает с любым потоком текстовых строк — без базы данных, без скриптового языка, без предобработки. sort и uniq — одни из старейших утилит Unix, и вместе они — рабочая лошадка анализа логов на лету. Ключевое: uniq сворачивает только соседние одинаковые строки, поэтому перед подсчётом всегда нужно сортировать.

К концу урока ты сможешь сортировать любой текстовый поток по содержимому или по полю, подсчитывать частоты и строить ранжированную таблицу.

Цель

После этого урока ты сможешь использовать sort для упорядочивания строк лексически и численно, использовать -k для сортировки по конкретному полю, использовать -r для разворота, использовать uniq -c для подсчёта последовательных дубликатов и использовать конвейер sort | uniq -c | sort -rn для построения таблицы частот от большего к меньшему.

1

sort упорядочивает строки лексически по умолчанию. Лексический порядок сравнивает символ за символом по значениям ASCII/Unicode. Это означает, что 10 сортируется перед 9, потому что '1' < '9' как символы — классическая ловушка.

printf '10\n9\n100\n2\n' | sort
# 10
# 100
# 2
# 9

Строки в ASCII-порядке (цифры сравниваются слева направо как символы). Для алфавитной сортировки строк это правильно, для числовых значений — нет.

-n переключает на численную сортировку. Числа разбираются как значения, а не последовательности символов.

printf '10\n9\n100\n2\n' | sort -n
# 2
# 9
# 10
# 100

Всегда используй -n, когда данные — столбец чисел. Забыть -n — одна из самых распространённых ошибок в sort внутри шелл-скриптов.

2

-r разворачивает порядок сортировки. В сочетании с -n даёт порядок от большего к меньшему.

printf '10\n9\n100\n2\n' | sort -rn
# 100
# 10
# 9
# 2

-u дедуплицирует: sort -u аналогично sort | uniq, но быстрее, потому что дедупликация происходит во время прохода сортировки.

printf 'b\na\nb\nc\na\n' | sort -u
# a
# b
# c

Используй sort -u, когда нужны только уникальные значения; используй sort | uniq -c, когда нужны уникальные значения со счётчиками.

3

-k N сортирует по полю N. По умолчанию sort считает пробельные символы разделителями полей. -k2 сортирует по второму разделённому пробелами полю; -k2,2 сортирует только по полю 2 (без -k2,2 сортировка продолжается по последующим полям как по критериям разрыва связей).

cat sizes.txt
# 150M  /var/log
# 2G    /usr
# 800M  /home
sort -k1 sizes.txt          # лексически по размеру: 150M, 2G, 800M (неверный порядок)
sort -k2 sizes.txt          # лексически по пути: /home, /usr, /var/log

Для численной сортировки по полю объедини -k с -n:

# Сортировать лог доступа по размеру ответа (поле 10 в Combined Log Format)
sort -k10 -n access.log | tail -5

Пять самых больших ответов в конце — в конце численно отсортированного списка. Добавь -r, чтобы поставить самый большой первым.

Для пользовательского разделителя добавь -t:

sort -t: -k3 -n /etc/passwd

Сортировать /etc/passwd по UID (поле 3), численно, с : как разделителем.

4

uniq -c подсчитывает последовательные одинаковые строки. Ему необходим отсортированный ввод — uniq сравнивает каждую строку только с непосредственно предыдущей. Если одинаковые строки не соседствуют, каждая группа получает свой счётчик.

printf 'error\nwarn\nerror\n' | uniq -c
# 1 error
# 1 warn
# 1 error          ← подсчитана отдельно, так как не соседствует

После sort:

printf 'error\nwarn\nerror\n' | sort | uniq -c
# 2 error
# 1 warn

Теперь обе строки error соседствуют, поэтому они свёртываются в один счётчик 2.

5

Идиома топ-N: sort | uniq -c | sort -rn. Три стадии работают вместе:

  1. sort — сделать одинаковые строки соседними.
  2. uniq -c — подсчитать каждую группу, производя строки вида 4 error.
  3. sort -rn — отсортировать численно в обратном порядке, чтобы элемент с наибольшим счётчиком был первым.

Добавь | head -10, чтобы получить топ 10.

# Топ-10 IP-адресов в лог доступа nginx (IP — поле 1)
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10
# Топ HTTP-кодов состояния
awk '{print $9}' access.log | sort | uniq -c | sort -rn

Формат вывода uniq -c: счётчик, затем пробел, затем значение. Второй sort -rn сортирует по счётчику, потому что он — первое поле. Эта идиома переносима в любую область: типы ошибок, user agent’ы, хэши SQL-запросов, названия событий.

Разбор примера

Найти 5 наиболее частых уровней логирования в лог-файле приложения.

Предположим, каждая строка начинается с ключевого слова уровня: ERROR, WARN, INFO, DEBUG.

grep -oE '^(ERROR|WARN|INFO|DEBUG)' app.log \
  | sort | uniq -c | sort -rn | head -5

grep -oE '^(ERROR|WARN|INFO|DEBUG)' извлекает только ключевое слово уровня в начале каждой строки (по одному на строку). Конвейер затем подсчитывает и ранжирует их.

Для syslog-файла, где уровень не в начале:

awk '{print $5}' /var/log/syslog | sort | uniq -c | sort -rn | head -10

Поле 5 в syslog — обычно имя процесса. Замени номер поля на тот, который содержит нужное измерение. Конвейер одинаков независимо от этого.

Почему это работает

На macOS (BSD sort) численная сортировка (-n) и разворот (-r) работают идентично. Основные отличия: BSD sort не поддерживает -V (версионная сортировка, например для сравнения v1.9 и v1.10), а нумерация полей -k одинакова. Идиома sort | uniq -c | sort -rn работает идентично на Linux и macOS. Флаг разделителя -t для sort также принимается BSD sort без проблем.

Частая ошибка

Самые распространённые ошибки sort: (1) забыть -n для числовых данныхsort по умолчанию выдаёт лексический порядок, и 10 сортируется перед 9; (2) запускать uniq -c без предварительной сортировки — несмежные одинаковые строки каждая получает свой счётчик 1, молча давая неверные частоты; (3) использовать -k N без -k N,Nsort -k2 сортирует по полю 2, но затем продолжает использовать последующие поля как критерии разрыва связей, что может давать неожиданный порядок при одинаковых значениях поля 2.

Проверь себя
Викторина

Ты запускаешь: printf 'b\na\nb\nc\n' | uniq -c без предварительной сортировки. Сколько строк в выводе?

Итог

sort упорядочивает строки лексически по умолчанию; -n переключает на численное сравнение; -r разворачивает; -k N,N сортирует по конкретному полю; -t РАЗД задаёт пользовательский разделитель полей. uniq -c подсчитывает последовательные одинаковые строки — входные данные должны быть отсортированы, иначе счётчики неверны. Идиома sort | uniq -c | sort -rn | head -N — универсальный конвейер таблицы частот: сделать одинаковые строки соседними, подсчитать их, ранжировать по убыванию счётчика, взять топ N. Этот шаблон работает без изменений на логах, потоках событий, CSV-колонках, выводе команд — на всём, что можно свести к одному значению на строку.

Практика

Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.

вспомнитьприменитьуглубить0 из 4 завершено

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.