Bash printf: форматирование вывода в терминале

Быстрые ссылки
Печать в терминал
Печать простых строк
Escape-последовательности
Использование переменных
Форматные строки
Другие трюки и особенности
Когда использовать printf, а когда echo
Команда Bash printf позволяет выводить текст в окно терминала с тонким контролем форматирования — гораздо больше, чем echo. Даже странности printf часто оказываются полезными. printf в Bash основан на функции printf из языка C, но между ними есть отличия: поведение Bash-версии более предсказуемо для скриптов и командной строки, но имеет свои нюансы (например, циклическое применение форматной строки к аргументам).
Печать в терминал
Писать что-то в терминал — одна из базовых операций: программа выводит информацию, а пользователь её читает. Многие утилиты Unix/Linux по умолчанию минималистичны и ничего не выводят, если всё прошло успешно. Но информативный вывод — важный элемент UX для скриптов и быстро выполняемых команд.
У Bash есть команда echo, которая умеет отображать строки и переменные. Однако printf добавляет гибкие возможности форматирования: строки с шаблонами, управление шириной поля, выравнивание, точность для чисел с плавающей запятой, печать символов по коду Unicode и специальная обработка escape-последовательностей.
Печать простых строк
Посмотрим на различия между echo и printf при простом выводе.
echo here are some wordsprintf here are some wordsecho выведет все слова, а printf без кавычек выведет только первое слово и не добавит перевод строки. Чтобы printf обработал все слова как единую строку, заключите текст в кавычки:
echo here are some wordsprintf "here are some words"Даже после этого printf не добавит перевод строки, если вы явно его не запросите. Новая строка вставляется через escape-последовательность \n:
echo here are some wordsprintf "here are some words\n"Иногда удобно комбинировать несколько вызовов printf: если первый вызов не заканчивается переводом строки, следующий вывод будет продолжен на той же строке:
printf "How-To " && printf "Geek\n"Первый printf не печатает перевод строки, поэтому вывод второго начинается сразу после “How-To”.
Escape-последовательности
Вот набор часто используемых escape-последовательностей в printf (Bash):
- \n — перевод курсора на новую строку.
- \r — возврат каретки: курсор возвращается в начало текущей строки и последующий текст начнёт перезаписывать строку.
- \t — символ табуляции.
- \v — вертикальная табуляция.
- \ — обратный слэш.
- \” — символ кавычки.
- \b — символ backspace.
Пример использования возврата каретки:
printf "Honey is the root of all evil\rMoney\n"printf печатает строку слева направо; при встрече \r курсор перемещается в начало строки и последующий текст перезаписывает предыдущий. В результате на экране остаётся “Money” вместо “Honey”.
Если вы хотите вывести символы кавычек или обратного слэша, их нужно экранировать:
printf "This is a \tTab, this is a quotation mark \", and this \\ is a Backslash\n"Использование переменных
С переменными printf работает так же, как и echo: подставляйте их через $:
printf "Home directory: $HOME\n"Важно: если переменная может содержать пробелы или escape-последовательности, лучше оборачивать её в кавычки и/или использовать формат %s.
Форматные строки
Форматная строка определяет шаблон вывода: она может содержать текст, escape-последовательности и форматные спецификаторы, которые указывают, какие типы аргументов ожидаются.
Наиболее распространённые спецификаторы (начинаются с %):
- %s — строка.
- %c — одиночный символ.
- %d — целое (signed integer).
- %f — число с плавающей точкой.
- %u — целое без знака.
- %o — восьмеричное представление.
- %x — шестнадцатеричное в нижнем регистре.
- %X — шестнадцатеричное в верхнем регистре.
- %e — плавающая точка в научной нотации (нижний регистр).
- %E — плавающая точка в научной нотации (верхний регистр).
- %% — символ процента.
Примеры:
printf "How-To %s\n" "Geek"printf "%s%s %s\n" "How" "-To" "Geek"В Bash между аргументами ставится пробел, в отличие от C, где аргументы разделяются запятой.
Числовые и форматные модификаторы
Ширина поля, выравнивание и точность управляются модификаторами формата. Пример — печать числа 15 в десятичной, восьмеричной и шестнадцатеричной системах:
printf "Dec: %d\nOct: %o\nHex: %x\n" 15 15 15Чтобы вывести шестнадцатеричный в верхнем регистре и задать минимальную ширину поля, используйте %2X или %02X (с автозаполнением нулями):
printf "Hex: %2X\n" 15printf "Hex: %02X\n" 15Для чисел с плавающей точкой можно контролировать общую ширину и количество знаков после точки:
printf "Floating point: %08.3f\n" 9.243546Ширина и точность применимы и к строкам: %10s распечатает строку в поле ширины 10, по умолчанию — справа. Чтобы левое выравнивание, добавьте минус:
printf "%-10s %d" "coats" 7 "shoes" 22 "Umbrellas" 3Чтобы ограничить максимальное число символов строки, используйте точность, например %10.6s — максимум 6 символов, видимая ширина 10.
printf ":%10.6s:\n" "coats" "shoes" "Umbrellas"printf ":%-10.6s:\n" "coats" "shoes" "Umbrellas"


Ширину можно передавать как аргумент, заменив числовой литерал на звёздочку * и передав целочисленное значение перед строкой:
printf "%*s\n" 20 "Rightmost" 12 "Middle" 5 "leftmost"
Другие трюки и особенности
Форматные спецификаторы применимы к значениям соответствующего типа независимо от того, поступают ли они как обычные аргументы или как результат выполнения команды.
Примеры:
Сумма двух чисел с подстановкой результата арифметики Bash:
printf "23+32=%d\n" $((23+32))Количество директорий в текущем каталоге:
printf "There are %d directories\n" $(ls -d */ | wc -l)Вывод имени текущего пользователя:
printf "Current user: %s\n" $(whoami)Если для спецификатора %s не передать аргумент, printf ничего напечатает в этом месте:
printf "One: %s two: %s\n" "Alpha"Если вместо строки передать числовое значение для %s, Bash напечатает его как строку; в отличие от C, это не приведёт к краху программы:
printf "One: %s two: %s\n" "Alpha" 777Если целый спецификатор %d не получает аргумента, printf распечатает 0:
printf "Integer: %d\n"Если %d получает нечисловую строку, Bash выведет предупреждение и распечатает 0:
printf "Integer: %d\n" "Seven"Unicode и коды символов
Символы можно генерировать по Unicode-кодовой точке с помощью \uXXXX (где XXXX — шестнадцатеричный код):
printf "The Euro symbol: \u20AC\n"Если вы передаёте escape-последовательности внутри аргумента, используйте формат %b, а не %s, чтобы printf интерпретировал их в качестве escape-последовательностей:
printf "%s" "\u20AC\n"printf "%b" "\u20AC\n"Первый пример не распознаёт Unicode-последовательность, а второй — распознаёт.
Когда использовать printf, когда echo
Простое правило:
- echo — для быстрых и простых сообщений, где не важны контроль над переносом строки, шириной поля или точностью числа.
- printf — когда нужен контролируемый, детерминированный и выровненный вывод: таблицы, отчёты, значения в фиксированных колонках, печать символов по коду, точное управление переводами строк.
Примеры ситуаций, где printf предпочтительнее:
- Логирование в файл с фиксированным форматом.
- Формирование таблиц результатов для обработки внешними утилитами.
- Вывод данных в сценариях, где отсутствие/наличие перевода строки критично.
Примеры, где echo проще и достаточен:
- Быстрый отладочный вывод.
- Простые уведомления для пользователя, где формат не важен.
Частые ошибки и когда printf может подвести
Важно знать ограничения и «подводные камни» printf:
- Не забывайте про кавычки: если передавать строки с пробелами без кавычек, они разобьются на отдельные аргументы.
- %d с некорректным аргументом выдаст 0 и сообщение об ошибке — это может скрыть баги, если вы не проверяете stderr.
- printf повторно применяет форматную строку к аргументам, если аргументов больше, чем форматных спецификаторов. Это может привести к неожиданным результатам, если вы этого не ожидаете.
- Различия между интерпретацией escape-последовательностей в разных оболочках: лучше использовать %b, когда требуется интерпретация в аргументе.
- Локаль влияет на вывод чисел (например, десятичный разделитель) и сортировку; для консистентного вывода в скриптах устанавливайте LC_ALL=C или явную локаль, если это важно.
Ментальные модели и эвристики
- Думайте о формате printf как о шаблоне таблицы: каждая спецификация — это «ячейка» столбца.
- Прежде чем формировать строку, спроектируйте ширины колонок и требуемую точность чисел.
- Используйте %b, когда аргументы могут содержать escape-последовательности, и %s для «сырых» строк.
- Тестируйте поведение с недостатком и избытком аргументов (edge-cases).
Шпаргалка (cheat sheet)
Добавить перевод строки: \n
Печать табуляции: \t
Печать обратного слэша: \
Формат целого: %d
Формат строки: %s
Формат шестнадцатеричного: %x / %X
Ширина поля: %10s / %-10s / %02X
Передача ширины как аргумента: %*s
Интерпретация escape-последовательностей в аргументе: %b
Роль‑ориентированные чеклисты
Для разработчика скриптов:
- Проверить, что все форматные спецификаторы соответствуют аргументам.
- Добавить кавычки вокруг строковых аргументов.
- Обработать случаи отсутствия аргументов и добавить валидацию.
- Протестировать поведение в разных локалях.
Для системного администратора:
- Использовать printf для логов с фиксированными столбцами.
- Установить локаль в скрипте, если логом будут пользоваться внешние системы.
- Убедиться в корректной обработке юникода/UTF-8.
Для новичка в Bash:
- Начать с простых примеров и добавлять форматирование по мере необходимости.
- Использовать echo для простого вывода, переходить на printf при необходимости выравнивания.
Мини‑методология: создание аккуратно выровненной таблицы
- Сначала соберите все данные и определите максимальную длину каждой колонки.
- Выберите ширину поля равную максимуму либо чуть больше, если нужны отступы.
- Используйте %-Ns для строк (левое выравнивание) и %Nd для чисел (правое выравнивание).
- Протестируйте с краевыми значениями (короткие и очень длинные строки).
- При необходимости используйте точность для усечения строк: %.Ns
Пример создания простой таблицы:
printf "%-15s %8s %8s\n" "Name" "Usage" "Count"
printf "%-15s %8s %8d\n" "cache" "MB" 1024SOP: как заменить echo на printf в скрипте
- Найдите случаи, где echo используется для выравнивания, табуляции или где важно отсутствие/наличие перевода строки.
- Замените echo на printf и добавьте соответствующий шаблон, например printf “%s\n” “$var”.
- Убедитесь, что все строки аргументов корректно экранированы.
- Протестируйте скрипт: особое внимание на локали, Unicode и пустые значения.
Пример замены:
До:
echo "User: $USER, Home: $HOME"После:
printf "User: %s, Home: %s\n" "$USER" "$HOME"Дерево принятия решения
flowchart TD
A[Нужен быстрый вывод без форматирования?] -->|Да| B[Используйте echo]
A -->|Нет| C[Требуется выравнивание, точность или escape-последовательности?]
C -->|Да| D[Используйте printf]
C -->|Нет| E[Используйте echo или printf по вкусу]
D --> F{Содержит ли аргумент escape-последовательности?}
F -->|Да| G[Используйте %b]
F -->|Нет| H[Используйте %s/%d/%f и т.д.]Кейсы тестирования и критерии приёмки
Критерии приёмки для функций, использующих printf в скриптах:
- Скрипт корректно работает для пустых, нормальных и слишком длинных значений.
- Вывод выровнен в соответствии с заданными ширинами поля.
- Unicode-символы отображаются корректно в целевой локали.
- Нет неожиданных переносов строк.
- Ошибки форматирования (несовпадающие спецификаторы) обрабатываются явно или документированы.
Тест-кейсы:
- Передать числовой аргумент в %s и проверить, что он выводится как строка.
- Передать строку в %d и проверить, что выводится 0 и присутствует сообщение об ошибке.
- Передать меньше аргументов, чем спецификаторов, и проверить поведение.
- Передать больше аргументов, чем спецификаторов, и проверить циклическое применение.
Примеры «когда это не работает» и альтернативы
- Нужен расширенный синтаксис шаблонов (например, табличные шаблоны с условным форматированием) — лучше использовать printf в сочетании с awk или printf внутри awk.
- Большие объёмы табличных данных — сгенерируйте CSV и используйте специализированные инструменты (csvkit, column, awk) для форматирования.
Альтернативы:
- echo — быстрый вывод без сложного форматирования.
- awk — мощное форматирование потоковых данных, регулярные выражения и вычисления.
- column — выравнивает колонки таблицы, удобно в комбинации с printf.
Галерея крайних случаев
Повторное использование форматной строки при множестве аргументов: если в формате 2 спецификатора, а аргументов 6, printf применит шаблон трижды.
Пустые значения: учтите, что пустая строка как аргумент всё равно расходует слот для спецификатора.
Локаль: вывод дробного числа может отличаться (запятая вместо точки) — контролируйте LC_ALL при необходимости.
1-строчный глоссарий
- format string — строка-шаблон с %-спецификаторами;
- width — минимальная ширина поля;
- precision — количество знаков после точки или максимальное число символов строки;
- %b — формат, который интерпретирует escape-последовательности в аргументе.
Заключение
printf — надёжный и мощный инструмент для контролируемого вывода в Bash. Он особенно полезен при построении аккуратно выровненных таблиц, при печати символов по коду и когда нужен предсказуемый контроль перевода строк и форматирования. echo остаётся полезным для простых случаев, но при переходе к более формализованным или машинно-обрабатываемым форматам предпочтительнее printf.
Важно: тестируйте поведение скриптов с различными данными и локалями, чтобы избежать сюрпризов в продакшене.
Краткое резюме:
- printf — используйте для точного форматирования.
- echo — для быстрых сообщений.
- Проверяйте соответствие спецификаторов аргументам и учитывайте локаль и Unicode.
Похожие материалы
Как демонстрировать экран в Google Meet
Как просмотреть старые версии сайта — Wayback Machine
Сочетания клавиш Проводника в Windows 10
Как отменить Paramount Plus — пошаговая инструкция
Как выключать, перезагружать и переводить PS5 в режим покоя