ЯдроКодаподготовка к экзаменам
Учебная платформа

Загружаем материалы

Подготавливаем материалы и навигацию по разделу.

Обработка текста: sed, cut, tr, sort, uniq и paste

Автор: · Обновлено

Конвейер обработки текста полезен, когда нужно привести выгрузку к одному виду, выбрать поле и посчитать повторения. Каждая стадия должна иметь понятный вход и выход: иначе исправление одного значения незаметно меняет остальные. Здесь работаем с маленьким списком заявок, результат которого можно проверить глазами.

Подготовить данные и выделить столбец

Выполните блок в Bash. Временный каталог не пересекается с файлами проекта, разделитель в примере — один символ двоеточия.

text_lab=$(mktemp -d)
printf 'alice:open:12\nbob:closed:7\nalice:open:3\n' >"$text_lab/requests.txt"
cut -d ':' -f1 "$text_lab/requests.txt"
cut -d ':' -f2,3 "$text_lab/requests.txt"

Первый результат — строки alice, bob, alice; второй сохраняет статус и число. В записи cut -d: -f1 опция -d задаёт разделитель, а -f1 выбирает первое поле, нумерация начинается с единицы. Без -d ожидается табуляция. Строка без разделителя по умолчанию проходит целиком; -s исключает такие строки. Для столбцов, разделённых переменным числом пробелов, обычно удобнее awk: два пробела у cut образуют пустое поле.

Изменить строки через sed

sed применяет команды к потоку и обычно пишет результат в stdout. Флаг g у подстановки меняет все совпадения внутри строки; без него заменяется только первое. Адрес перед командой ограничивает строки, к которым она применяется.

sed 's/:open:/:waiting:/g' "$text_lab/requests.txt"
sed -n '2p' "$text_lab/requests.txt"
sed '/^bob:/d' "$text_lab/requests.txt"
sed -i.bak 's/^bob:closed:/bob:review:/' "$text_lab/requests.txt"
diff -u "$text_lab/requests.txt.bak" "$text_lab/requests.txt" || true

-n отключает обычную печать, поэтому 2p выводит только вторую строку. Последняя подстановка записывает результат и оставляет .bak; сравнение показывает замену одной строки. Чтобы заменить строку полностью, используйте, например, sed '2c\bob:review:7' файл. Точка и звёздочка в шаблоне — операторы регулярного выражения, а & в правой части означает найденное совпадение. Для буквальной замены пользовательских значений потребуется экранирование; произвольный ввод нельзя просто вставлять в программу sed.

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

cut -d: -f1 "$text_lab/requests.txt" | LC_ALL=C sort | uniq -c
sort -t: -k3,3n "$text_lab/requests.txt"

Первый конвейер выдаёт два появления alice и одно bob. uniq объединяет только соседние одинаковые строки, поэтому без сортировки первое и третье появления останутся раздельными. sort -u удобно для одного списка уникальных значений, но не даёт частоты. Числовой ключ -k3,3n сортирует третье поле как 3, 7, 12; обычная строковая сортировка могла бы поставить 12 перед 3. Локаль влияет на порядок букв и числовые форматы; LC_ALL=C делает техническую сортировку воспроизводимой.

Символы и склейка строк

printf 'a,b,c\n' | tr ',' '\n'
printf 'OK\r\n' | tr -d '\r'
printf 'alice\nbob\n' >"$text_lab/names"
printf '12\n7\n' >"$text_lab/counts"
paste -d: "$text_lab/names" "$text_lab/counts"

tr заменяет или удаляет символы, а не слова: им нельзя корректно заменить слово cat на dog в предложении. Удаление \r применяйте к тексту с известными окончаниями строк, не к бинарному файлу. paste склеивает соответствующие строки и выдаёт alice:12, bob:7; при разной длине файлов появляются пустые поля. Это соединение по номеру строки, а не по ключу пользователя.

Ошибка и диагностика

Команда sed ... file >file обнулит вход ещё до чтения: перенаправление выполняет shell. Используйте отдельный результат и сравнение либо осознанное -i.bak. Если количество записей неожиданно изменилось, выполните стадии отдельно и сравните wc -l. Для CSV с кавычками и запятыми внутри значения нужны средства, понимающие CSV, а не механическое разделение по запятой.

Практика

Добавьте заявку bob:open:21. Получите число заявок каждого пользователя, затем строки в порядке возрастания третьего поля. Переименуйте только статус open, сохранив исходник. Проверьте, что число строк равно четырём, сумма чисел не изменилась, а .bak содержит старые статусы. Объясните, почему перестановка sort и uniq -c меняет ответ. Удалите учебный каталог после сравнения.

Что важно запомнить

Разделитель, регулярное выражение и порядок записей — часть формата данных. Проверяйте их до изменения файла; небольшая контрольная выборка помогает обнаружить потерю строк раньше, чем конвейер попадёт в автоматизацию.

Частые вопросы

Почему sed заменил больше текста, чем ожидалось?

Шаблон трактуется как регулярное выражение. Ограничьте начало или конец строки, проверьте метасимволы и сначала просмотрите stdout без записи исходника.

Можно ли считать уникальные IP через uniq?

Можно после извлечения IP и сортировки. Если нужен порядок первого появления, сортировка его уничтожает: используйте таблицу уже встреченных значений в awk.

Почему cut не подходит для произвольного CSV?

Разделитель внутри кавычек является частью поля. cut не хранит состояние кавычек и разделит такую запись неверно, даже если несколько простых примеров выглядят правильно.

Источники