Пайпы и конвейеры команд

Соединяем простые команды в мощные цепочки обработки данных.

Пайп (конвейер) — это оператор |, который передаёт стандартный вывод одной команды на стандартный ввод следующей.

Философия Unix: маленькие команды в цепочке

Unix-команды делают одну вещь, но хорошо. Сила в том, чтобы соединять их пайпами. Вывод левой команды становится вводом правой:

cat access.log | grep ERROR | wc -l

Эта цепочка читает лог, оставляет строки со словом ERROR и считает их. Каждая команда не знает о соседях — она просто читает stdin и пишет stdout.

cat access.log
     │ stdout
     ▼
   grep ERROR
     │ stdout
     ▼
   wc -l ──▶ число строк с ERROR

Полезные команды-фильтры

В конвейерах постоянно встречаются sort (сортировка), uniq (схлопывание дубликатов соседних строк), head/tail (начало/конец).

cat names.txt | sort | uniq -c | sort -rn | head -3

Вывод:

     12 Анна
      8 Борис
      5 Вера

Разберём: отсортировали имена, uniq -c посчитал повторы, ещё раз отсортировали по числу в обратном порядке (-rn), взяли топ-3. Классический способ найти самые частые значения.

Here-doc: подача многострочного текста

Иногда команде нужно подать на вход несколько строк прямо из скрипта. Для этого есть here-doc — блок <<:

cat <<EOF
Строка один
Строка два
EOF

Вывод:

Строка один
Строка два

Всё между <<EOF и закрывающим EOF подаётся в stdin команды. Слово-разделитель может быть любым; если написать <<'EOF' в кавычках, подстановка переменных внутри отключается.

Как работает под капотом

Bash запускает все команды конвейера одновременно, как параллельные процессы, и соединяет их специальным каналом в памяти (pipe). Левый процесс пишет в канал, правый из него читает; когда буфер заполнен, писатель ждёт читателя. Поэтому данные текут «потоком» и не нужно хранить весь результат целиком — конвейер обрабатывает даже гигабайтные логи, не загружая их в память.

Частые ошибки

  • Лишний cat. cat file | grep x избыточно — grep x file читает файл сам. Это называют «бесполезным использованием cat».
  • uniq без sort. uniq схлопывает только СОСЕДНИЕ дубликаты, поэтому почти всегда перед ним ставят sort.
  • Ловить ошибку только последней команды. Код возврата конвейера — это код последней команды; промежуточные сбои легко пропустить (лечится опцией pipefail, разберём позже).

Итог

  • Пайп | направляет stdout слева на stdin справа, образуя конвейер.
  • Команды-фильтры grep, sort, uniq, head комбинируются в мощные цепочки.
  • uniq требует предварительного sort; here-doc <<EOF подаёт многострочный текст на вход.
Проверьте себя
1. Что делает оператор | (пайп) в Bash?
AСоздаёт файл
BПередаёт stdout левой команды на stdin правой
CСравнивает две команды
DЗапускает команды по очереди независимо
2. Почему перед uniq обычно ставят sort?
Asort ускоряет uniq
Buniq схлопывает только соседние одинаковые строки, поэтому их сперва нужно сгруппировать
Cuniq не работает без sort вообще
DТак требует синтаксис Bash
3. Зачем нужен here-doc (<<EOF)?
AЧтобы создать переменную
BЧтобы подать команде многострочный текст на stdin прямо из скрипта
CЧтобы перенаправить ошибки
DЧтобы запустить цикл