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 и %e | printf '%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 |
%.2f | 2 знака после точки (с округлением) | %.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