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

14

yashОболочка имеет printfвстроенный, согласно его инструкции .

Тем не менее, это то, что я вижу в yashоболочке с конфигурацией по умолчанию:

kk@eeyore ~ $ command -v printf
/usr/bin/printf
kk@eeyore ~ $ 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
Это встроенный - обычный , а не специальный встроенный. Если вы не уверены в разнице между специальными и обычными встроенными модулями или в поведении, предписанном стандартом (см. Поиск и выполнение команд 1.eia), который требует наличия двоичного файла PATHдля обычной встроенной чтобы быть казненным - тогда, пожалуйста, сделайте свой вопрос об этом.
мосви
1
@mosvy Это была деталь стандарта, которая была мне неизвестна. Если вы хотите превратить это в ответ, я был бы счастлив. Я не думаю, что мне нужно было бы обновить вопрос, чтобы это было подходящим ответом, так как я не знал об этой конкретной детали. Или сам напишу позже.
Кусалананда

Ответы:

14

yashОболочка делает есть, и делает использование, встроенный в версию printf(и других утилит). Просто оказывается, что он очень педантично соответствует POSIX, так как формулирует результат command -vиtype команд.

Как комментирует mosvy , стандарт POSIX требует, чтобы обычная встроенная команда была доступна как внешняя команда $PATHдля выполнения встроенной версии команды.

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

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

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

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

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

      [...]

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

Это означает, что вывод command -v printfозначает, что printfкоманда была найдена в пути поиска, а выводtype printf добавляет к этому, что команда является встроенной.

Поскольку printfкоманда была найдена в пути поиска, и поскольку она является обычной встроенной в оболочку, yashбудет вызываться ее встроенная версия команды . Если бы путь неprintf был найден, и если оболочка работала в корректном режиме POSIX, вместо этого возникла бы ошибка.yash

yashгордится тем, что является очень POSIX-совместимой оболочкой, и это также верно, если мы посмотрим, что говорит POSIXcommand -v :

-v

Записать строку в стандартный вывод, которая указывает путь или команду, которая будет использоваться оболочкой в ​​текущей среде выполнения оболочки (см. Среда выполнения оболочки ), чтобы вызывать command_name, но не вызывать command_name.

  • Утилиты, обычные встроенные утилиты , command_namesвключая <slash>символ, и любые функции, определяемые реализацией, которые обнаруживаются с помощью PATHпеременной (как описано в разделе « Поиск и выполнение команд» ), должны записываться как абсолютные имена путей .
Кусалананда
источник
3
Кто-нибудь знает, почему POSIX имеет это требование для существования внешней команды перед запуском встроенной команды?
Студог
@studog Вы можете задать этот вопрос как отдельный новый вопрос, возможно, ссылаясь на этот ответ и / или вопрос.
Кусалананда
6

Оболочка Watanabe имеет три вида встроенных модулей, подробно описанных в руководстве пользователя. Здесь также перечислены все встроенные команды, но нужно сделать вывод, что что-то является «обычной» встроенной командой из-за отсутствия каких-либо примечаний, говорящих о том, что команда «особая» или «полу особая» встроенный. Обычные встроенные модули не отмечены.

printfявляется одним из таких «обычных» встроенных. В основном режиме он вызывается всегда , независимо от того, найдена ли внешняя команда с этим именем.

$ PATH = / usr / bin 
$ printf
printf: эта команда требует операнд
$ type printf
printf: обычный встроенный в / usr / bin / printf
$
$ PATH = / 
$ printf
printf: эта команда требует операнд
$ type printf
printf: обычный встроенный (не найден в $ PATH)
$

Но когда posixly-correctопция оболочки установлена, она является только встроенной, если внешняя команда может быть найдена в PATH.

$ set --posixly-correct
$
$ PATH = / usr / bin 
$ printf
printf: эта команда требует операнд
$
$ PATH = / 
$ printf
yash: нет такой команды `printf '
$

Это на самом деле соответствует тому, что говорится в Спецификации Single Unix, и как минимум с 1997 года.

Он отличается от оболочки Z, оболочки 93 Korn, оболочки 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 = / type printf; printf"
printf - это встроенная оболочка
printf: использование: printf [-v var] формат [аргументы]
% / bin / exec -a sh dash -c "PATH = /; тип printf; printf"
printf - это встроенная оболочка
sh: 1: printf: использование: формат printf [arg ...]
% 

Однако не работает, printfкогда он не PATHвключен, поведение оболочки PD Korn, оболочки Heirloom Bourne и оболочки MirBSD Korn; потому что они не имеют printfвстроенного в первую очередь. ☺

% / bin / exec -a sh `команда -v ksh` -c" PATH = /; тип printf; printf "
printf не найден
sh: printf: не найдено
% / bin / exec -a sh `команда -v oksh` -c" PATH = /; тип printf; printf "
printf не найден
sh: printf: не найдено
% / bin / exec -a sh `команда -v jsh` -c" PATH = /; тип printf; printf "
printf не найден
sh: printf: не найдено
% / bin / exec -a sh mksh -c "PATH = /; тип printf; printf"
printf не найден
sh: printf: не найдено
% ksh -c "type printf; printf"
printf - отслеживаемый псевдоним для / usr / bin / printf
использование: формат printf [аргументы ...]
% oksh -c "type printf; printf"
printf - отслеживаемый псевдоним для / usr / bin / printf
использование: формат printf [аргументы ...]
% jsh -c "type printf; printf"
printf хэшируется (/ usr / bin / printf)
использование: формат printf [аргументы ...]
% mksh -c "type printf; printf"
printf - отслеживаемый псевдоним для / usr / bin / printf
использование: формат printf [аргументы ...]
$
JdeBP
источник
Хорошо! Спасибо за подтверждение и за добавление специфичных для оболочки битов в мои знания! Мне больше нравится эта оболочка.
Кусалананда
-1

Формулировка может быть улучшена.

Если оболочка находится в режиме posix set --posixly-correct:

Для обычных встроенных модулей, которые не существуют в PATH, это печатается:

pushd: a regular built-in (not found in $PATH)

Это четкое описание: это встроенный файл, но в PATH нет исполняемого файла с таким именем.

Однако для обычных встроенных модулей, имена которых также существуют в PATH, это печатается:

echo: a regular built-in at /bin/echo

Который, кажется, подразумевает, что исполняемый файл в / bin / echo будет выполнен (чего не будет). Я полагаю , что переход от atк also found in PATH at:

echo: a regular built-in also found in PATH at /bin/echo

сделал бы лучшее описание. Возможно, заключив это в круглые скобки (как это сделал другой ответ), можно было бы сделать это лучше.


В режиме POSIX, не регулярные встроенное не будет работать , если он не будет также найден в PATH.

Тем не менее, оба (POSIX) специальные:

break colon continue dot eval exec exit export
readonly return set shift times trap unset

И yash полу-особенный (не особенный для POSIX):

alias bg cd command false fc fg getopts jobs
kill pwd read true umask unalias wait

встроенные функции все еще работают.

Исаак
источник