DevToys Web Pro iconDevToys Web ProБлог
Переведено с помощью LocalePack logoLocalePack
Оцените нас:
Попробуйте расширение для браузера:
← Назад к блогу

Сортировка строк, удаление дубликатов и фильтрация текста: практическое руководство

7 мин чтения

Построчная обработка текста — сортировка списка, удаление дубликатов, очистка пустых строк — встречается в работе разработчика постоянно. Вы вставляете фрагмент лога, столбец 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. Старые окружения и некоторые цели транспиляции это не гарантируют. Если порядок важен, используйте явный паттерн с seen Set, а не 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 без сортировки — нет.

Все описанные в этом руководстве операции доступны в Утилитах строк — сортировка, дедупликация, фильтрация и обрезка прямо в браузере без передачи данных на сервер. Для смежных операций с текстом смотрите Руководство по текстовым инструментам и сравнение операций со списками.