CLI AI

Убрать повторяющиеся строки — с сортировкой и без

2026-08-01

sort -u file.txt убирает повторяющиеся строки и сортирует остаток; awk '!seen[$0]++' file.txt убирает их и оставляет исходный порядок. Что нужно вам — зависит от того, несёт ли порядок смысл: в логе он несёт всегда. Один uniq не делает ни того, ни другого.

1. Почему uniq в одиночку не помогает

clai
$ clai убери повторы из access.log→ uniq access.log10.0.0.710.0.0.310.0.0.710.0.0.910.0.0.310.0.0.710.0.0.1

Файл вернулся без изменений. uniq схлопывает только соседние одинаковые строки, а в живом файле повторы разбросаны. Отсюда и классическая связка sort | uniq.

2. Убрать повторы и отсортировать

clai
$ clai убери повторы и отсортируй файл→ sort -u access.log10.0.0.110.0.0.310.0.0.710.0.0.9

sort -u делает обе работы за один проход — короче и быстрее, чем пайп в uniq.

3. Убрать повторы, сохранив порядок

clai
$ clai убери повторы, но оставь исходный порядок строк→ awk '!seen[$0]++' access.log10.0.0.710.0.0.310.0.0.910.0.0.1

Вот настоящее отличие от sort -u: остаётся первое вхождение каждой строки, порядок не тронут. Это важно для логов и всего, что пишется по времени. Плата — память: awk держит все уникальные строки, и на файлах в десятки гигабайт это заметно.

4. Сколько раз встречается каждая строка

clai
$ clai посчитай, сколько раз встречается каждая строка→ sort access.log | uniq -c | sort -rn      3 10.0.0.7      2 10.0.0.3      1 10.0.0.9      1 10.0.0.1

Тот самый рецепт «топ-N» для логов. uniq -c считает, второй sort -rn поднимает частые наверх.

5. Только те строки, что повторялись

clai
$ clai покажи только строки, которые встречаются больше одного раза→ sort access.log | uniq -d10.0.0.310.0.0.7

-d оставляет только дубли, -u — наоборот, только одиночные строки: в этом файле 10.0.0.1 и 10.0.0.9. Удобно, когда сравниваешь два списка.

6. Дедупликация по одному полю

clai
$ clai оставь по одной строке на каждый URL→ awk '!seen[$2]++' req.logGET /a 200GET /b 404

$2 — второе поле. Так схлопывают лог по URL, по IP или по идентификатору сессии, сохраняя целиком первую встреченную строку.

Gotchas

  • sort -u file > file обнуляет файл. Проверено: шелл обрезает файл под запись раньше, чем sort успевает его прочитать, и на выходе ноль строк. Правильно — sort -u file -o file: у sort есть штатный флаг записи в собственный вход, и он работает.
  • uniq требует отсортированного ввода. Без sort перед ним он молча вернёт почти тот же файл. Не ошибка, а тихо неверный ответ.
  • Порядок и сортировка — разные требования. sort -u даёт алфавитный порядок, awk '!seen[$0]++' — исходный. Для логов почти всегда нужен второй, а показывают обычно первый.

Related questions

Как найти строки, общие для двух файлов? comm -12 <(sort a.txt) <(sort b.txt). Оба входа должны быть отсортированы — для этого и нужна подстановка процессов.

Как не учитывать регистр? sort -uf сравнивает без учёта регистра; awk '!seen[tolower($0)]++' делает то же, сохраняя порядок.

А если файл не влезает в память? sort -u сбрасывает промежуточные данные во временные файлы и переваривает вход больше оперативной памяти; вариант с awk на том же файле может её исчерпать.

See also

CliAI сам выбирает между вариантом с сортировкой и вариантом с сохранением порядка по вашей формулировке и сначала показывает команду. Поставить одной строкой.