
Оболочка yash
имеет printf
встроенный,согласно его руководству.
Однако вот что я вижу в yash
оболочке с конфигурацией по умолчанию:
$ command -v printf
/usr/bin/printf
$ type printf
printf: a regular built-in at /usr/bin/printf
Встроенный printf
в эту оболочку или нет? Результат аналогичен для ряда других предположительно встроенных утилит, которые также доступны как внешние команды.
Для сравнения, в pdksh
( ksh
в OpenBSD, где printf
находитсянетвстроенный):
$ command -v printf
/usr/bin/printf
$ type printf
printf is /usr/bin/printf
И в bash
(гдеprintf
являетсявстроенный):
$ command -v printf
printf
$ type printf
printf is a shell builtin
решение1
Оболочкаyash
делаетимеют и используют встроенную версию printf
(и другие утилиты). Просто она очень педантично соответствует POSIX в том, как она формулирует результат команд command -v
и type
.
Как комментирует mosvyстандарт POSIX требует, чтобы обычная встроенная команда была доступна в качестве внешней команды $PATH
для выполнения встроенной версии команды.
Этосоответствующий текст из стандарта:
Поиск и выполнение команд
Если простая команда приводит к имени команды и необязательному списку аргументов, то должны быть выполнены следующие действия:
Если имя команды не содержит символов <слэш>, то произойдет первый успешный шаг в следующей последовательности:
а. Если имя команды совпадает с именем специальной встроенной утилиты, то будет вызвана эта специальная встроенная утилита.
[...]
- е. В противном случае поиск команды будет осуществляться с использованием переменной среды PATH, как описано в разделе Переменные среды XBD:
- я.Если поиск успешен:
- а.Если система реализовала утилиту как обычную встроенную функцию или как функцию оболочки, она должна быть вызвана на этом этапе поиска пути.
- б. В противном случае оболочка выполняет утилиту в отдельной среде утилит [...]
[...]- ii. Если поиск не удался, команда завершится с ошибкой со статусом выхода 127, а оболочка выведет сообщение об ошибке.
- Если имя команды содержит хотя бы один <слэш>, [...]
Это означает, что вывод command -v printf
означает, что printf
командабылнайдено в пути поиска, в то время как вывод type printf
добавляет к этому, что команда является обычной встроенной.
Так как printf
команда была найдена в пути поиска и так как она является обычной встроенной в оболочку,yash
вызовет встроенную версию команды. Если бы printf
былонетнайден в пути, и если бы yash
оболочка работала в правильном режиме POSIX, вместо этого была бы сгенерирована ошибка.
yash
гордится тем, что является оболочкой, полностью соответствующей POSIX, и это также верно, если мы посмотрим начто говорит POSIX оcommand -v
:
-v
Запишите в стандартный вывод строку, указывающую путь или команду, которая будет использоваться оболочкой в текущей среде выполнения оболочки (см.Среда выполнения оболочки), чтобы вызвать
command_name
, но не вызыватьcommand_name
.
- Коммунальные услуги,обычные встроенные утилиты,
command_names
включая<slash>
символ, и любые функции, определенные реализацией, которые найдены с использованиемPATH
переменной (как описано вПоиск и выполнение команд),должны быть записаны как абсолютные пути.
решение2
Оболочка Watanabe имеет три вида встроенных команд, подробно описанных в ее руководстве. Все встроенные команды также перечислены там, но нужно сделать вывод, что что-то является "обычной" встроенной командой изотсутствиелюбой заметки, говорящей о том, что команда является "специальной" или "полуспециальной" встроенной. Обычные встроенные не отмечены.
printf
является одним из таких "обычных" встроенных. В основном режиме этовсегдавызывается независимо от того, найдена ли внешняя команда с таким именем.
$ПУТЬ=/usr/bin $printf printf: эта команда требует операнда $тип printf printf: обычная встроенная функция в /usr/bin/printf $ $ПУТЬ=/ $printf printf: эта команда требует операнда $тип printf printf: обычная встроенная функция (не найдена в $PATH) $
Но когда posixly-correct
установлена опция shell, она является встроенной только в том случае, если внешняя команда может быть найдена в PATH
.
$установить --posixly-correct $ $ПУТЬ=/usr/bin $printf printf: эта команда требует операнда $ $ПУТЬ=/ $printf yash: такой команды `printf' нет $
На самом деле это соответствует тому, что говорится в Единой спецификации Unix, которая существует по крайней мере с 1997 года.
Он отличается от оболочки Z, оболочки Korn 93, оболочки Bourne Again и оболочки Debian Almquist, ни одна из которых не реализует и не документирует такое поведение для обычных встроенных функций. Например, оболочка Z документирует, что обычные встроенные функциивсегданайденный,дошаг, который ищет PATH
. То же самое делает и оболочка Debian Almquist. И это то, что делают все эти оболочки, даже если они вызваны sh
с их опциями включения POSIX.
%/bin/exec -a sh zsh -c "PATH=/ ; тип printf ; printf" printf — встроенная в оболочку команда zsh:printf:1: недостаточно аргументов %/bin/exec -a sh ksh93 -c "PATH=/ ; тип printf ; printf" printf — встроенная в оболочку команда Использование: printf [параметры] формат [строка ...] %/bin/exec -a sh bash --posix -c "PATH=/ тип printf ; printf" printf — встроенная в оболочку команда printf: использование: printf [-v var] формат [аргументы] %/bin/exec -a sh dash -c "PATH=/ ; тип printf ; printf" printf — встроенная в оболочку команда sh: 1: printf: использование: формат printf [arg ...] %
Однако поведение оболочек PD Korn, Heirloom Bourne и MirBSD Korn заключается в том, что они не запускаются printf
, когда они не включены ; поскольку у них изначально нет встроенного . ☺PATH
printf
%/bin/exec -a sh `command -v ksh` -c "PATH=/ ; тип printf ; printf" printf не найден sh: printf: не найдено %/bin/exec -a sh `command -v oksh` -c "PATH=/ ; тип printf ; printf" printf не найден sh: printf: не найдено %/bin/exec -a sh `command -v jsh` -c "PATH=/ ; тип printf ; printf" printf не найден sh: printf: не найдено %/bin/exec -a sh mksh -c "PATH=/ ; тип printf ; printf" printf не найден sh: printf: не найдено %ksh -c "тип printf ; printf" printf — отслеживаемый псевдоним для /usr/bin/printf использование: формат printf [аргументы ...] %oksh -c "тип printf ; printf" printf — отслеживаемый псевдоним для /usr/bin/printf использование: формат printf [аргументы ...] %jsh -c "тип printf ; printf" printf хэшируется (/usr/bin/printf) использование: формат printf [аргументы ...] %mksh -c "тип printf ; printf" printf — отслеживаемый псевдоним для /usr/bin/printf использование: формат printf [аргументы ...] $