Немного не понимаю, является ли printf в оболочке yash встроенной командой или нет.

Немного не понимаю, является ли printf в оболочке yash встроенной командой или нет.

Оболочка 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для выполнения встроенной версии команды.

Этосоответствующий текст из стандарта:

Поиск и выполнение команд

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

  1. Если имя команды не содержит символов <слэш>, то произойдет первый успешный шаг в следующей последовательности:

    • а. Если имя команды совпадает с именем специальной встроенной утилиты, то будет вызвана эта специальная встроенная утилита.

      [...]

    • е. В противном случае поиск команды будет осуществляться с использованием переменной среды PATH, как описано в разделе Переменные среды XBD:
      • я.Если поиск успешен:
        • а.Если система реализовала утилиту как обычную встроенную функцию или как функцию оболочки, она должна быть вызвана на этом этапе поиска пути.
        • б. В противном случае оболочка выполняет утилиту в отдельной среде утилит [...]
          [...]
      • ii. Если поиск не удался, команда завершится с ошибкой со статусом выхода 127, а оболочка выведет сообщение об ошибке.
  2. Если имя команды содержит хотя бы один <слэш>, [...]

Это означает, что вывод 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, когда они не включены ; поскольку у них изначально нет встроенного . ☺PATHprintf

%/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 [аргументы ...]
$

Связанный контент