Printf

Материал из Ай да Linux Wiki
Версия от 07:11, 2 февраля 2011; Langator (обсуждение | вклад) (Новая страница: «== Printf как замена команды echo == Эта команда была создана для замены всем знакомой команды echo...»)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к навигации Перейти к поиску

Printf как замена команды echo

Эта команда была создана для замены всем знакомой команды echo. Возможности команды echo ограничены, кроме того, в разных ветках Unix'а оказались разные ее версии, что приводит к несовместимости. Поэтому Posix рекомендует пользоваться командой printf. Команда printf выводит АРГУМЕНТ на стандартный вывод (как правило, экран дисплея), используя при этом определенный ФОРМАТ.

 $ printf 'ФОРМАТ' 'АРГУМЕНТ'

Эта команда была создана для замены всем знакомой команды echo (настолько древней, что даже имя ее автора не известно).


Самое первое, что следует прояснить: по умолчанию команда printf не переводит строку по завершении. Это выглядит так:

 [ya@antony ~]$ printf '%s' 'alex'
 
 alex[ya@antony ~]$  

Следующее приглашение командной строки находится на той же самой строке что и вывод предыдущей команды. Это очень неудобно, поэтому в ФОРМАТ приходится добавлять символ новой строки (\n):

 [ya@antony ~]$ printf '%s\n' 'alex'
 
 alex
 
 [ya@antony ~]$ 

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

Вот как выглядит команда printf в виде, полностью дублирующем команду echo:

  $ printf '%b\n' 'Это заклинание заменит команду echo'
  
  Это заклинание заменит команду echo

Обратите внимание, что мы взяли аргумент в кавычки, чтобы получить его в виде одной строки. Если бы мы этого не сделали, то имели бы столбик, так как программа воспринимает выражения, разделенные пробелом, как множественные аргументы, и обрабатывает каждый в соответствии с заданным форматом:

 $ printf '%b\n' Это заклинание заменит команду echo
 
 Это 
 
 заклинание 
 
 заменит 
 
 команду 
 
 echo

Если нам нужно использовать команду printf для просмотра переменных окружения, то кавычки не нужны:

 $ printf '%b\n' $PATH
 
 /home/ya/bin:/usr/local/bin:/usr/bin:/bin:/usr/bin:/usr/games:/usr/X11R6/bin

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

 $ printf '%b\n' '$PATH'
 
 $PATH

Но довольно о замене команды echo, займемся непосредственно командой printf.

Описание и использование

Представление аргумента

N Нормальное десятичное число. Например 177

0N Восьмеричное число. Например 024.

0xN и 0XN Шестнадцатеричные числа. Например 0?41.

(обычные кавычки перед любой буквой) Интерпретируется как кодовый номер этой буквы в текущей кодировке. С кириллицей не работает.

'А (одинарные кавычки перед любой буквой) Интерпретируется как кодовый номер этой буквы в текущей кодировке. С кириллицей не работает.

Форматы команды printf

Вообще говоря, синтаксис команды printf взят от функции printf() языка программирования Си (и еще дюжины других). Но далеко не все знакомы с Си, поэтому мы внимательно рассмотрим все тонкости синтаксиса этой команды.

ФОРМАТ пишется в командной строке непосредственно после самой команды и заключается в кавычки - двойные или одинарные. Собственно говоря, кавычки нужны не всегда, но лучше их ставить, во избежание недоразумений. Это полезная привычка. (А ведь большинство привычек - вредные).

%b Рассматривает аргумент как строку, при этом интерпретирует все управляющие символы, содержащиеся в ней.

%s Рассматривает аргумент как просто как строку.

%c Рассматривает аргумент как символ, при этом берется первый символ выражения или строки.

%q Преобразует строку к виду, пригодному к использованию в качестве ввода в шелл.

Здесь необходимы пояснения. Допустим, мы хотим напечатать на экране фразу:

 Ваш,
 
 Алексей Дмитриев

Для этого дадим следующую команду:

 $ printf '%b\n' 'Ваш,\nАлексей Дмитриев'
 
 Ваш,
 
 Алексей Дмитриев

А теперь вместо формата %b применим формат %q:

 $ printf '%q\n' 'Ваш,\nАлексей Дмитриев'
 
 $'\320\222\320\260\321\210,\\n\320\220\320\273\320\265\320\272\321\201\320\265\320\271   \320\224\320\274\320\270\321\202\321\200\320\270\320\265\320\262'

Кажется, произошла какая-то ошибка или сбой. Но это не так; подставим вывод команды в качестве аргумента команды printf '%b\n', но уже безо всяких дополнительных кавычек (все необходимые кавычки содержатся в выводе команды):

 $ printf '%b\n' $'\320\222\320\260\321\210,\\n\320\220\320\273\320\265\320\272\321\201\320\265\320\271   \320\224\320\274\320\270\321\202\321\200\320\270\320\265\320\262'
 
 Ваш,
 
 Алексей Дмитриев

Больше того, этот же вывод можно использовать в качестве аргумента для других команд, скажем echo -e (опция -e позволяет команде echo интерпретировать специальные символы, в частности символ новой строки (\n):

 $ echo -e $'\320\222\320\260\321\210, \\n\320\220\320\273\320\265\320\272\321\201\320\265\320\271   \320\224\320\274\320\270\321\202\321\200\320\270\320\265\320\262'
   
 Ваш,
 
 Алексей Дмитриев

Вот какой интересный формат %q! Однако продолжим.

Дальше идут всевозможные форматы представления чисел.

%d Представляет аргумент в виде десятичного числа, могущего иметь знак (+ или -).

%u Представляет аргумент в виде десятичного числа, не имеющего знака.

  $ printf '%d\n' -777
  
  -777

%i То же, что и предыдущее.

%o Представляет аргумент в виде не имеющего знака восьмеричного числа.

  $ printf '%o\n' 777
  
  1411

%x Представляет аргумент в виде не имеющего знака шестнадцатеричного числа. Буквы пишутся в нижнем регистре.

  $ printf '%x\n' 177
  
  b1

%X Представляет аргумент в виде не имеющего знака шестнадцатеричного числа, при этом буквы пишутся в верхнем регистре.

  $ printf '%X\n' 177
  
  B1

%f Интерпретирует аргумент как число с плавающей запятой.

  $ printf '%f\n' 17,7
  
  17,700000

%e Интерпретирует аргумент с удвоенной точностью (double precision), при этом выводит его в формате <N>+/-e<N>.

 $ printf '%e\n' 177
 
 1,770000e+02

%E То же, что и предыдущее, только с заглавной буквой Е.

Вот и все форматы, я привел их для встроенной в bash команды printf.

Модификаторы форматов

Для большей гибкости представления строк или чисел, поддерживаются несколько модификаторов форматов. Модификаторы вставляются между символом процента и буквой, характеризующей формат, например:

 [ya@antony ~]$ printf '%50s\n' 'this field is 50 characters wide...'
 
              this field is 50 characters wide...


(С кириллицей не работает).

Модификаторы: Любое число Обозначает минимальную ширину колонки, если текст короче, то строки дополняются пробелами. (См. пример выше).

  1. Альтернативный формат для чисел, см. ниже.

- Выравнивание текста по левому краю (стандарно - по правому краю)

0 Дополняет числа нулями, а не пробелами. Применяется при заданной ширине колонки (в примере 50). Пример:

 $ printf '%050d\n' '177'
 
 00000000000000000000000000000000000000000000000177

space Дополняет положительные числа пробелами, а отрицательные знаками "минус" (-).

+ Пишет все числа со знаками плюс или минус.

Альтернативный формат для чисел

%#o Восьмеричные числа пишутся с нулем впереди, если они сами не нулевые:

 $ printf '%#0o\n' '177'
 
 0261

%#x, %#X Шестнадцатеричные числа пишутся с или впереди, если они сами не нулевые:

 $ printf '%#x\n' '177'
 
 0xb1

%#g, %#G Числа с плавающей запятой пишутся с последующими нулями, в количестве, определяемом данным разрешением. Обычно последующие нули не пишутся:

 $ printf '%#g\n' '17,7'
 
 17,7000

%# со всеми числовыми форматами, кроме d, o, x, X Всегда ставит десятичную запятую, даже если знаков после запятой нет:

 $ printf '%#ge\n' '177'
 
 177,000

Точность разрешения

Точность разрешения чисел с плавающей запятой и чисел с удвоенной точностью (double precision) можно регулировать следующим образом:

 $ printf "%.20f\n" 4,3
 
 4,30000000000000000017

Внимание: не прозевайте точку в записи формата!

Можно вместо числа знаков поставить астериск, тогда количество знаков ставится перед самим аргументом:

 $ printf "%.*f\n" 10 4,3
 
 4,3000000000

Для строк точность разрешения определяет максимальное число выводимых символов (максимальную ширину колонки текста).

Для целых чисел - задает число выводимых знаков (добавляет нули).

Управляющие символы языка Си, работающие с командой printf

\" Двойные кавычки

\NNN Символ с восьмеричным значением NNN (от 1 до 3 цифр)

\\ Обратный слэш (\)

\a Звуковой сигнал

\b Забой

\c Не производить дальнейшую обработку данных

\f Перевод страницы

\n Новая строка

\r Возврат каретки

\v Вертикальная табуляция

\xHH Символ с шестнадцатеричным кодом HH (1 или 2 цифры)

\uHHHH Символ Unicode (ISO/IEC 10646) с шестнадцатеричным кодом HHHH (4 цифры)

\UHHHHHHHH Символ Unicode с шестнадцатеричным кодом HHHHHHHH (8 цифр)

%% Символ %

Еще несколько примеров

1. Вывести шестнадцатеричное число в десятичной форме:

 $ printf '%d\n' '-0x41'
 
 -65

2. Вывести десятичное число в восьмеричной форме:

 $ printf '%o\n' 65
 
 101

3. Узнать кодовый номер буквы А (англ):

 $ printf '%d\n' \'A
 
 65

4. Пример, служащий домашним заданием:

 $ printf '%b\n' "$0" "$@"
 
 /bin/bash

Кто понял, в чем тут дело, сообщите мне, пожалуйста. Я лично не понял.

Опции команды printf

Опция -v ПЕРЕМЕННАЯ_ОКРУЖЕНИЯ

Записывает аргумент в указанную переменную окружения. При этом затирает все, что там было прописано. Осторожно!

 $ printf -v PATH '%b\n' '/usr/local/bin'
 
 $ printf '%b\n' $PATH
 
 /usr/local/bin
 
 $ su
 
 bash: su: команда не найдена


Хорошо, что в начале статьи я привел пример, в котором была записана моя $PATH, поэтому смог восстановить.

Опции --help и --version общеизвестны и рассмотрены не будут.

Примечание: В мане GNU-версии команды вы не найдете и половины этой информации, а будете отосланы к синтаксису языка Си.

Резюме команды printf

Исследуя подобные команды, получаешь настоящее удовольствие, маны практически отсутствуют, найденные статьи относятся к другим версиям команды. Почти все приходится добывать методом эксперимента. Сколько еще удивительных особенностей таит команда printf, узнают только те, кто станет пользоваться ей в повседневной жизни.

Должен предупредить, что собрал в этой статье все, что сумел "нарыть" по поводу всех версий этой команды. Поэтому некоторые варианты могут не срабатывать в ваших версиях.



Информация взята с open-club.ru