← Весь справочник

echo и printf

Вывод текста из скрипта — echo с его ловушками и printf с форматами %s %d %f %x %q %b

echo печатает аргументы через пробел и добавляет перевод строки. Это удобно для простых сообщений, но поведение echo зависит от опций и оболочки. printf печатает строго по шаблону-формату — так выводят таблицы, числа с нужной точностью, строки без перевода строки и любые данные «как есть». В bash обе команды встроенные, их справка — help echo и help printf.

Синтаксис

echo [-neE] [аргумент…]
printf [-v переменная] формат [аргумент…]

Опции echo

ОпцияЧто делает
-nне добавлять перевод строки в конце
-eпонимать escape-последовательности в аргументах (\n, \t, …)
-Eне понимать escape-последовательности (так по умолчанию в bash)

Других опций у встроенного echo нет: -- он не понимает и печатает как текст.

Escape-последовательности

Работают в echo -e, в формате printf, в аргументах printf для %b и внутри $'…'.

ЗаписьЧто это
\n / \t / \rперевод строки / табуляция / возврат каретки
\\сам обратный слэш
\a / \b / \f / \vзвонок / забой / перевод страницы / вертикальная табуляция
\e (\033)символ ESC — начало цветовых кодов терминала: \e[31m красный, \e[1m жирный, \e[0m сброс
\xHHбайт в шестнадцатеричном виде: \x41 → A
\0NNN (echo, %b) / \NNN (формат printf)байт в восьмеричном виде: \0101 / \101 → A
\uHHHH / \UHHHHHHHHсимвол Юникода: \u0416 → Ж
\cоборвать вывод: всё после \c, включая перевод строки, не печатается

Спецификаторы printf

Формат — строка с обычным текстом и спецификаторами %…. Каждый спецификатор забирает следующий аргумент.

СпецификаторЧто печатаетПример → результат
%sстроку как естьprintf '%s\n' 'a\tb' → a\tb
%bстроку, раскрывая в ней escape-последовательностиprintf '%b\n' 'a\tb' → a<таб>b
%d, %iцелое число со знакомprintf '%d' 0x1f → 31
%uбеззнаковое целоеprintf '%u' -1 → 18446744073709551615
%fдробное с 6 знаками после точкиprintf '%f' 2.5 → 2.500000
%e / %gэкспоненциальная запись / самая короткая из %f и %eprintf '%e' 12345.678 → 1.234568e+04
%x / %Xшестнадцатеричное, строчными / заглавнымиprintf '%x' 255 → ff
%oвосьмеричноеprintf '%o' 8 → 10
%cпервый символ аргументаprintf '%c' hello → h
%qстроку, экранированную для повторного ввода в оболочкуprintf '%q' "a b'c" → a\ b\'c
%(формат)Tдату по шаблону strftime; аргумент — Unix-время, -1 — сейчасprintf '%(%F %T)T\n' -1
%%сам знак процентаprintf '100%%' → 100%

Числовые аргументы можно писать как 0x1f (шестнадцатеричное), 010 (восьмеричное = 8) и "'A" — код символа (printf '%d' "'A" → 65).

Ширина, точность, флаги

Общий вид спецификатора: %[флаги][ширина][.точность]тип.

ЗаписьЧто делаетПример → результат
%8sширина 8, выравнивание вправо[%8s] с hi → [ hi]
%-8sширина 8, выравнивание влево[%-8s] с hi → [hi ]
%08dдополнить нулями слева%08d с 42 → 00000042
%+dвсегда показывать знак%+d с 5 → +5
%.2f2 знака после точки (с округлением)%.2f с 3.14159 → 3.14
%8.3fширина 8 и 3 знака после точки[%8.3f] с 2.5 → [ 2.500]
%.3sобрезать строку до 3 байт%.3s с abcdef → abc
%*d / %-*sширину берёт из аргументаprintf '%*d' 5 42 → 42
%#x / %#oдобавить префикс 0x / 0%#x с 255 → 0xff

Повторное применение формата и -v

Если аргументов больше, чем спецификаторов, printf прогоняет формат по кругу, пока аргументы не кончатся. Недостающие аргументы считаются пустой строкой (для чисел — нулём):

printf '%s\n' a b c          # три строки: a, b, c
printf '%s=%s\n' a 1 b 2 c   # a=1, b=2, c=

printf -v имя формат … не печатает, а кладёт результат в переменную — без подоболочки $(…):

printf -v id '%05d' 42       # id=00042

Примеры

# сообщение без перевода строки, курсор остаётся на той же строке
echo -n "Подожди… "; sleep 1; echo "готово"

# каждый элемент массива — на своей строке (надёжнее, чем echo "${arr[@]}")
arr=("первый файл" второй третий)
printf '%s\n' "${arr[@]}"

# ровная таблица: имя влево в 10 символов, число вправо в 6
printf '%-10s %6s\n' NAME SIZE
printf '%-10s %6d\n' config 120 data.db 20480

# число с двумя знаками после точки и с ведущими нулями
printf '%.2f\n' 3.14159        # 3.14
printf '%03d\n' 7              # 007

# перевести число в шестнадцатеричное и обратно
printf '%x\n' 255              # ff
printf '%d\n' 0xff             # 255

# цветной текст: красный, затем сброс
printf '\e[31m%s\e[0m\n' "ОШИБКА"

# строка, которую можно безопасно вставить в команду
printf '%q\n' "file with spaces.txt"   # file\ with\ spaces.txt

# текущая дата без вызова date
printf '%(%Y-%m-%d %H:%M)T\n' -1

# вывести в stderr
printf 'ошибка: %s\n' "нет файла" >&2

Подводные камни

  • echo не понимает --. echo -- -n печатает -- -n. А если в переменной окажется -n или -e, echo "$x" воспримет её как опцию и ничего не напечатает. Для произвольных данных пиши printf '%s\n' "$x".
  • echo без -e не раскрывает \n. echo "a\tb" печатает буквально a\tb. В других оболочках (например, sh → dash) echo раскрывает их всегда — поэтому в переносимых скриптах используй printf.
  • Не подставляй данные в формат. printf "$var\n" ломается, если в $var есть % или \: строка скидка 100% даёт ошибку invalid format character и код 1. Правильно — printf '%s\n' "$var".
  • printf сам не добавляет перевод строки. Без \n в формате следующая строка вывода приклеится к этой.
  • %d только для целых. printf '%d' 3.5 печатает 3, пишет invalid number в stderr и возвращает код 1. Для дробных — %f / %.Nf.
  • Округление %.0f — к ближайшему чётному: 0.5 → 0, 1.5 → 2, 2.5 → 2.
  • Ширина и точность считаются в байтах, а не в символах. Кириллическая буква занимает 2 байта, поэтому printf '[%6s]' абв печатает [абв] без отступа, а %.2s от абв — одну букву. Таблицы с кириллицей выравнивай через column -t.
  • Пустой массив всё равно даёт строку. printf '%s\n' "${arr[@]}" при пустом arr выведет одну пустую строку: формат применяется хотя бы раз.

См. также

read · redirection · variables · column · date