Сортировка строк, удаление дубликатов и фильтрация текста: практическое руководство
Построчная обработка текста — сортировка списка, удаление дубликатов, очистка пустых строк — встречается в работе разработчика постоянно. Вы вставляете фрагмент лога, столбец CSV, список импортов или конфигурационный блок и хотите навести порядок за несколько секунд. Инструмент Утилиты строк выполняет все эти операции прямо в браузере, не отправляя данные на сервер.
Когда браузерный инструмент удобнее sort | uniq
Конвейер sort file.txt | uniq мощный, но обращаться к терминалу оправдано не всегда. Три ситуации, в которых браузерный инструмент выигрывает:
- Нет доступа к терминалу. Вы работаете на корпоративном компьютере с ограничениями, Chromebook или в веб-IDE. Вставить данные в инструмент займёт две секунды; найти терминал — десять минут.
- Небольшой разовый список. Если входные данные — 20 строк из таблицы или Slack-сообщения, писать shell-скрипт избыточно. Вставил, нажал, скопировал.
- Конфиденциальные данные. Сортировать список внутренних имён пользователей или API-ключей через онлайн-сервис, который логирует запросы, — риск. Клиентский инструмент обрабатывает всё локально: данные не покидают вкладку браузера.
Для больших файлов, скриптовых конвейеров и автоматизации CLI-инструменты по-прежнему предпочтительнее. В разделах ниже приведены эквивалентные команды для каждой операции, чтобы воспроизвести результат в скрипте.
Стратегии сортировки
Сортировка бывает не только алфавитной. Правильная стратегия зависит от содержимого строк. Сравнение основных вариантов:
| Стратегия | Как работает | Лучше всего для | Флаг CLI |
|---|---|---|---|
| Алфавитная | По байтовому коду (ASCII / UTF-8) | Идентификаторы кода, ключи, простые списки слов | sort |
| Без учёта регистра | Верхний регистр приводится к нижнему перед сравнением | Смешанные ключи конфига, имена хостов | sort -f |
| Натуральная (человеческая) | Числа в строке сравниваются как числа: file10 идёт после file9 | Имена файлов, версионные строки | sort -V |
| Числовая | Разбирает ведущее число и сравнивает как целое или вещественное | Строки, начинающиеся со счётчиков, задержек, размеров | sort -n |
| С учётом локали | Использует Intl.Collator для корректного порядка акцентов и диакритики | Имена людей, слова на языках с не-ASCII символами | sort -k1,1 с LC_ALL=lang |
| Обратная | Любая из вышеперечисленных в убывающем порядке | Временные метки от новых к старым, счётчики по убыванию | sort -r |
Распространённые ловушки при сортировке
Неправильный тип сортировки даёт незаметно неверный результат. Три ловушки, в которые разработчики попадают регулярно:
- IP-адреса как текст. При лексикографической сортировке
192.168.1.10оказывается раньше192.168.1.9, потому что"1"(первая цифра числа10) меньше"9". Для корректного результата нужно сортировать по числовому значению каждого октета или по целочисленному представлению всего адреса. - Версии с
sort -n. Числовая сортировка читает только ведущее число, поэтому2.10.0и2.9.0оба становятся2и сравниваются как равные. Используйтеsort -V(версионная сортировка). - Даты в локальном формате.
20.04.2026и04/20/2026сортируются совершенно по-разному в зависимости от локали. Нормализуйте даты к ISO 8601 (2026-04-20) перед сортировкой — ISO-даты правильно сортируются как обычные строки.
Подходы к дедупликации
Удаление дубликатов кажется простым, но определение «дубликата» важно:
- Точное совпадение — строки считаются дубликатами только при побайтовом равенстве. Именно так работают
sort -uиuniqпосле сортировки. - Без учёта регистра —
Errorиerrorсчитаются одинаковыми. Полезно при дедупликации ключевых слов логов или ключей конфига. - Обрезка пробелов — ведущие и завершающие пробелы удаляются перед сравнением, поэтому
" apple"и"apple"считаются одинаковыми. Устраняет артефакты копирования из таблиц. - Нормализация Unicode (NFC) — один и тот же символ может иметь несколько Unicode-представлений. Буква
eи комбинацияe + ̀выглядят одинаково, но отличаются побайтово. NFC-нормализация сводит их к единому виду перед сравнением. Важно при работе с текстом из macOS (использует NFD) и Windows-файлов (NFC).
Когда порядок важен, используйте дедупликацию с сохранением порядка вставки, а не сортировку с последующим uniq. Эквивалент в CLI — awk '!seen[$0]++': сохраняет только первое вхождение каждой строки без изменения порядка.
# Сохранить первое вхождение, порядок не изменять
awk '!seen[$0]++' input.txt
# Дедупликация без учёта регистра, порядок сохраняется
awk '!seen[tolower($0)]++' input.txt
# Сортировка + дедупликация (исходный порядок не сохраняется)
sort -u input.txtУдаление пустых строк и обработка пробелов
Пустые строки бывают двух видов, требующих разного подхода:
- Истинно пустые строки — содержат только символ перевода строки. Легко удаляются с помощью
grep -v '^$'илиsed '/^$/d'. - Строки из пробелов и табуляций — содержат пробельные символы, но нет видимого содержимого. Простой фильтр пустых строк их пропускает. Используйте
grep -v '^\s*$', чтобы поймать оба варианта.
Отдельная операция — обрезка (trim): удаление ведущих и завершающих пробелов в каждой строке без удаления самой строки. Это отличается от удаления пустых строк. После обрезки строки, состоявшие из одних пробелов, становятся пустыми и могут быть удалены вторым проходом.
# Удалить истинно пустые строки
grep -v '^$' input.txt
# Удалить строки из пробелов тоже
grep -v '^s*$' input.txt
# Обрезать пробелы в каждой строке (GNU sed)
sed 's/^[[:space:]]*//;s/[[:space:]]*$//' input.txt
# Схлопнуть несколько пустых строк в одну
cat -s input.txt
# или
tr -s '
' < input.txtРеальные сценарии использования
Построчные утилиты максимально полезны в следующих ситуациях:
- Фильтрация логов. Вставьте блок строк лога, удалите дубликаты, чтобы увидеть уникальные сообщения об ошибках, затем отсортируйте по префиксу серьёзности или временной метке. Намного быстрее, чем grep, когда точный паттерн ещё не известен.
- Очистка конфигурационных файлов. В
.env-файлах, записяхhostsи allowlist-ах nginx со временем накапливаются дубликаты. Сортировка и дедупликация помогают обнаружить конфликты и уменьшить объём файла. - Дедупликация списков импортов. При слиянии двух файлов с Python-импортами или TypeScript-операторами
importотсортируйте алфавитно и удалите дубликаты, чтобы получить канонический список. - Анализ заголовков CSV. Вставьте первую строку нескольких CSV-экспортов, дедуплицируйте для получения объединения имён столбцов, затем отсортируйте для сравнения охвата между датасетами.
Эквиваленты в командной строке
Для автоматизации и больших файлов полезно знать соответствующие shell-команды:
# Алфавитная сортировка
sort input.txt
# Сортировка с удалением дубликатов
sort -u input.txt
# Числовая сортировка (ведущее число в каждой строке)
sort -n input.txt
# Версионная / натуральная сортировка
sort -V input.txt
# Обратная сортировка
sort -r input.txt
# Сортировка без учёта регистра
sort -f input.txt
# Сохранить порядок, удалить дубликаты (awk)
awk '!seen[$0]++' input.txt
# Удалить пустые и пробельные строки
grep -v '^s*$' input.txt
# Схлопнуть соседние дубликаты (входные данные должны быть отсортированы)
uniq input.txt
# Обрезать пробелы в каждой строке
sed 's/^[[:space:]]*//;s/[[:space:]]*$//' input.txtПримеры кода
Те же операции в коде приложения, а не в командной строке:
// JavaScript — сортировка и дедупликация с сохранением порядка вставки
const lines = text.split('\n').filter(Boolean);
// Точная дедупликация, порядок вставки сохраняется (ES2015+)
const unique = Array.from(new Set(lines));
// Дедупликация без учёта регистра, сохранить первое вхождение
const seen = new Set();
const uniqueCI = lines.filter(line => {
const key = line.toLowerCase();
if (seen.has(key)) return false;
seen.add(key);
return true;
});
// Сортировка с учётом локали (акценты, диакритика)
const collator = new Intl.Collator('ru', { sensitivity: 'base' });
const sorted = [...unique].sort((a, b) => collator.compare(a, b));
// Натуральная (человеческая) сортировка
const natural = [...lines].sort((a, b) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' })
);# Python — сортировка и дедупликация
lines = text.splitlines()
# Точная дедупликация, порядок вставки сохраняется (Python 3.7+)
unique = list(dict.fromkeys(lines))
# Дедупликация без учёта регистра, сохранить первое вхождение
seen = set()
unique_ci = []
for line in lines:
key = line.casefold()
if key not in seen:
seen.add(key)
unique_ci.append(line)
# Сортировка
sorted_lines = sorted(unique)
# Сортировка с учётом локали (требует PyICU или модуль locale)
import locale
locale.setlocale(locale.LC_ALL, 'ru_RU.UTF-8')
locale_sorted = sorted(unique, key=locale.strxfrm)
# Удалить пустые и пробельные строки
non_empty = [line for line in lines if line.strip()]Подводные камни в коде
Несколько ловушек, которые стоит знать до выпуска кода с построчной обработкой:
Setсохраняет порядок вставки только начиная с ES2015. Старые окружения и некоторые цели транспиляции это не гарантируют. Если порядок важен, используйте явный паттерн сseenSet, а неArray.from(new Set(...)).- Ловушки нормализации Unicode. Две строки, выглядящие одинаково, могут иметь разные байтовые представления в зависимости от источника (macOS использует NFD, Windows и веб — NFC). Всегда нормализуйте перед сравнением:
line.normalize('NFC')в JavaScript,unicodedata.normalize('NFC', line)в Python. - Окончания строк CRLF против LF. Файл с Windows-переносами строк (
\r\n) оставит символ\rв конце каждой строки после разбивки по\n. Строки"apple\r"и"apple"не считаются дубликатами при точном сравнении. Нормализуйте переносы строк заранее:text.replace(/\r\n/g, '\n')или открывайте файл в текстовом режиме Python (по умолчанию). sort -uпротивsort | uniq. Результат одинаков для точного совпадения, ноuniqудаляет только соседние дубликаты — он требует отсортированных входных данных. На несортированном вводеsort -uкорректен, аuniqбез сортировки — нет.
Все описанные в этом руководстве операции доступны в Утилитах строк — сортировка, дедупликация, фильтрация и обрезка прямо в браузере без передачи данных на сервер. Для смежных операций с текстом смотрите Руководство по текстовым инструментам и сравнение операций со списками.