Légèrement confus quant à savoir si printf dans le shell yash est une commande intégrée ou non

14

La yashcoque a un printfintégré, selon son manuel .

Cependant, c'est ce que je vois dans un yashshell avec une configuration par défaut:

kk@eeyore ~ $ command -v printf
/usr/bin/printf
kk@eeyore ~ $ type printf
printf: a regular built-in at /usr/bin/printf

Est printfun intégré dans ce shell ou non? Le résultat est similaire pour un certain nombre d'autres utilitaires supposés intégrés qui sont également disponibles en tant que commandes externes.

A titre de comparaison, dans pdksh( kshsur OpenBSD, où printfn'est pas intégré):

$ command -v printf
/usr/bin/printf
$ type printf
printf is /usr/bin/printf

Et dans bash(où printf est intégré):

$ command -v printf
printf
$ type printf
printf is a shell builtin
Kusalananda
la source
1
C'est un intégré - un régulier , pas un intégré spécial . Si vous êtes confus au sujet de la différence entre les incorporations spéciales et régulières , ou le comportement exigé par la norme (voir la recherche et l'exécution de commandes 1.eia) - qui nécessite qu'un binaire doit exister PATHpour un incorporé régulier à exécuter - alors veuillez poser votre question à ce sujet.
2019
1
@mosvy C'était un détail de la norme qui m'était inconnu. Si vous voulez en faire une réponse, je serais heureux. Je ne pense pas que j'aurais besoin de mettre à jour la question pour que ce soit une réponse appropriée, car je n'étais pas au courant de ce détail particulier. Ou je l'écrirai moi-même plus tard.
Kusalananda

Réponses:

14

Le yashshell possède et utilise une version intégrée de printf(et d'autres utilitaires). Il se trouve qu'il est très conforme à la norme POSIX dans la façon dont il formule le résultat des commandes command -vet type.

Comme le commente mosvy , la norme POSIX requiert qu'une commande intégrée standard soit disponible en tant que commande externe $PATHpour que la version intégrée de la commande soit exécutée.

Voici le texte pertinent de la norme :

Recherche et exécution de commandes

Si une commande simple donne un nom de commande et une liste facultative d'arguments, les actions suivantes doivent être effectuées:

  1. Si le nom de la commande ne contient aucun caractère <slash>, la première étape réussie de la séquence suivante doit se produire:

    • une. Si le nom de la commande correspond au nom d'un utilitaire intégré spécial, cet utilitaire intégré spécial doit être appelé.

      [...]

    • e. Sinon, la commande doit être recherchée à l'aide de la variable d'environnement PATH comme décrit dans Variables d'environnement XBD:
      • je. Si la recherche réussit:
        • une. Si le système a implémenté l'utilitaire en tant que fonction intégrée standard ou en tant que fonction shell, il doit être invoqué à ce stade de la recherche de chemin.
        • b. Sinon, le shell exécute l'utilitaire dans un environnement utilitaire séparé [...]
          [...]
      • ii. Si la recherche échoue, la commande échoue avec un état de sortie de 127 et le shell écrit un message d'erreur.
  2. Si le nom de la commande contient au moins une <barre oblique>, [...]

Cela signifie que la sortie de command -v printfsignifie que la printfcommande a été trouvée dans le chemin de recherche, tandis que la sortie de type printfajoute à cela que la commande est une fonction intégrée standard.

Étant donné que la printfcommande a été trouvée dans le chemin de recherche, et puisqu'il s'agit d'un shell intégré normal, yashappellera sa version intégrée de la commande . Si l' printfon ne trouve dans le chemin, et si la yashcoque est en cours d' exécution en mode POSIX ment correct, une erreur aurait été générée à la place.

yashse targue d'être un shell très conforme à POSIX, et cela est également vrai si nous regardons ce que POSIX dit à propos decommand -v :

-v

Écrivez une chaîne dans la sortie standard qui indique le chemin d'accès ou la commande qui sera utilisée par le shell, dans l'environnement d'exécution du shell actuel (voir Environnement d'exécution du shell ), pour invoquer command_name, mais ne pas invoquer command_name.

  • Les utilitaires, les utilitaires intégrés standard , command_namesy compris un <slash>caractère, et toutes les fonctions définies par l'implémentation qui sont trouvées en utilisant la PATHvariable (comme décrit dans Recherche et exécution de commandes ), doivent être écrits comme des chemins absolus .
Kusalananda
la source
3
Quelqu'un sait-il pourquoi POSIX a cette exigence pour qu'une commande externe existe avant d'exécuter la commande intégrée?
studog
@studog Vous voudrez peut-être poser cette question en tant que nouvelle question distincte, en vous référant éventuellement à cette réponse et / ou question.
Kusalananda
6

La coque Watanabe a trois sortes de fonctions intégrées, décrites en détail dans son manuel. Toutes les commandes intégrées y sont également répertoriées, mais il faut en déduire que quelque chose est une commande intégrée "régulière" de l' absence de note indiquant que la commande est une "spéciale" ou une "semi-spéciale" intégré. Les fonctions intégrées standard ne sont pas marquées.

printfest un tel intégré "régulier". En mode natif, il est toujours appelé, qu'il existe ou non une commande externe trouvée sous ce nom.

$ PATH = / usr / bin 
$ printf
printf: cette commande nécessite un opérande
$ type printf
printf: un standard intégré dans / usr / bin / printf
$
$ PATH = / 
$ printf
printf: cette commande nécessite un opérande
$ type printf
printf: un intégré standard (introuvable dans $ PATH)
$

Mais lorsque l' posixly-correctoption shell est définie, elle n'est intégrée que si la commande externe peut être trouvée sur le PATH.

$ set --posixly-correct
$
$ PATH = / usr / bin 
$ printf
printf: cette commande nécessite un opérande
$
$ PATH = / 
$ printf
yash: aucune commande de ce type `printf '
$

Ceci est en fait conforme à ce que dit la spécification Unix unique, et le dit depuis au moins 1997.

Il diffère du shell Z, du shell 93 Korn, du shell Bourne Again et du shell Debian Almquist. Le shell Z, par exemple, documente que les intégrations régulières sont toujours trouvées, avant l'étape de recherche PATH. Il en va de même pour le shell Debian Almquist. Et c'est ce que font tous ces shells, même s'ils sont invoqués comme shavec leurs options d'activation POSIX.

% / bin / exec -a sh zsh -c "PATH = /; type printf; printf"
printf est un shell intégré
zsh: printf: 1: pas assez d'arguments
% / bin / exec -a sh ksh93 -c "PATH = /; type printf; printf"
printf est un shell intégré
Utilisation: printf [options] format [string ...]
% / bin / exec -a sh bash --posix -c "PATH = / type printf; printf"
printf est un shell intégré
printf: usage: printf [-v var] format [arguments]
% / bin / exec -a sh tiret -c "CHEMIN = /; tapez printf; printf"
printf est un shell intégré
sh: 1: printf: utilisation: format printf [arg ...]
% 

Cependant, ne fonctionne pas printfquand il n'est pas sur le PATHcomportement du shell PD Korn, du shell Heirloom Bourne et du shell MirBSD Korn; parce qu'ils n'ont pasprintf intégré en premier lieu. ☺

%  / bin / exec -a sh `command -v ksh` -c" PATH = /; type printf; printf "
printf introuvable
sh: printf: introuvable
% / bin / exec -a sh `command -v oksh` -c" PATH = /; type printf; printf "
printf introuvable
sh: printf: introuvable
% / bin / exec -a sh `command -v jsh` -c" PATH = /; type printf; printf "
printf introuvable
sh: printf: introuvable
% / bin / exec -a sh mksh -c "PATH = /; type printf; printf"
printf introuvable
sh: printf: introuvable
% ksh -c "type printf; printf"
printf est un alias suivi pour / usr / bin / printf
utilisation: format printf [arguments ...]
% oksh -c "type printf; printf"
printf est un alias suivi pour / usr / bin / printf
utilisation: format printf [arguments ...]
% jsh -c "type printf; printf"
printf est haché (/ usr / bin / printf)
utilisation: format printf [arguments ...]
% mksh -c "type printf; printf"
printf est un alias suivi pour / usr / bin / printf
utilisation: format printf [arguments ...]
$
JdeBP
la source
Bien! Merci d'avoir confirmé et d'avoir ajouté les bits spécifiques au shell à ma connaissance! J'aime déjà plus cette coquille.
Kusalananda
-1

Le libellé pourrait être amélioré.

Si le shell est en mode posix set --posixly-correct::

Pour les incorporations régulières qui n'existent pas dans le PATH, ceci est imprimé:

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

Ce qui est une description claire: c'est une fonction intégrée mais il n'y a pas d'exécutable du même nom dans le PATH.

Cependant, pour les fonctions intégrées régulières dont le nom existe également dans le CHEMIN, ceci est imprimé:

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

Ce qui semble impliquer que l'exécutable de / bin / echo sera exécuté (ce qui ne le sera pas). Je suggère qu'un changement de atà also found in PATH at:

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

ferait une meilleure description. Peut-être que la mise entre parenthèses (comme l'a fait l'autre réponse) pourrait l'améliorer.


En mode POSIX, aucune fonction intégrée normale ne fonctionnera à moins qu'elle ne se trouve également dans le PATH.

Cependant, les deux (POSIX) spéciaux:

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

Et semi-spécial de yash (pas spécial pour POSIX):

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

les builtins fonctionnent toujours.

Isaac
la source