Est-ce que shell est portable pour exécuter une command sur la même ligne après l'assignation des variables?

Existe-t-il une norme couvrant la portabilité de l'exécution d'une command après l'affectation de variables sur la même ligne?

APPLE="cider" echo hi 

Comment portable est quelque chose comme ça? Où cela va-t-il fonctionner et où ne le fera-t-il pas?

En outre: mes scripts shell commencent par #! / Bin / sh si cela fait une différence.

Tant que vous utilisez un shell compatible POSIX, oui.

A partir de la définition POSIX du langage de command shell : (points pertinents en gras)

Une "command simple" est une séquence d' assignations de variables facultatives et de redirections, dans n'importe quelle séquence, éventuellement suivie de mots et de redirections, terminée par un opérateur de contrôle.

Lorsqu'une command simple donnée doit être exécutée (c'est-à-dire lorsqu'une construction conditionnelle telle qu'une list AND-OR ou une instruction de cas n'a pas contourné la command simple), les expansions, affectations et redirections suivantes sont effectuées à partir de le début du text de la command jusqu'à la fin:

  1. Les mots qui sont reconnus comme des affectations variables ou des redirections selon les règles de grammaire de Shell sont enregistrés pour le traitement aux étapes 3 et 4.

  2. Les mots qui ne sont pas des assignations variables ou des redirections doivent être développés. Si des champs restnt après leur expansion, le premier champ doit être considéré comme le nom de la command et les champs restants sont les arguments de la command.

  3. Les redirections doivent être effectuées comme décrit dans Redirection .

  4. Chaque affectation de variable doit être étendue pour l'extension tilde, l'extension de paramètre, la substitution de command, l'expansion arithmétique et la suppression de devis avant d'affecter la valeur.

Dans la list précédente, l'ordre des étapes 3 et 4 peut être inversé pour le traitement des utilitaires embeddeds spéciaux; voir Utilitaires embeddeds spéciaux .

Si aucun résultat de nom de command n'apparaît, les affectations de variables affecteront l'environnement d'exécution en cours. Dans le cas contraire, les affectations de variables doivent être exscopes pour l'environnement d'exécution de la command et ne doivent pas affecter l'environnement d'exécution actuel (sauf pour les encarts spéciaux).


En outre, oui #!/bin/sh importe. De la définition POSIX de sh :

L'utilitaire sh est un interpréteur de langage de command qui exécutera les commands lues à partir d'une string de command line, de l'input standard ou d'un file spécifié. L'application doit s'assurer que les commands à exécuter sont exprimées dans la langue décrite dans le langage de command Shell .

Donc, fondamentalement, il dit que sh doit suivre les règles que nous avons abordées ci-dessus.

Donc, tant que vous êtes sur un operating system compatible POSIX, vous êtes bon.

Pour répondre à la deuxième question, incomplètement (le nombre de coquilles est ahurissant )

 % for sh in dash ksh93 mksh rc fish bash zsh csh tcsh jsh; do printf '%s\n' "$sh: $($sh -c 'var=foo echo hi')" done dash: hi ksh93: hi mksh: hi rc: hi fish: Unknown command “var=foo”. Did you mean “set var foo”? For information on assigning values to variables, see the help section on the set command by typing “help set” Standard input: var=foo echo hi ^ fish: bash: hi zsh: hi var=foo: Command not found. csh: var=foo: Command not found. tcsh: jsh: hi 

Dans la plupart des coquilles modernes de Korn, cela fonctionnera. Mais je ne pense pas que ce soit un standard, je suis sûr que quelqu'un comme Stéphane Chazelas sait à quel point c'est courant.

Oui, ça a été comme ça depuis les premiers jours de

http://www.freebsd.org/cgi/man.cgi?query=sh&apropos=0&sektion=0&manpath=Unix+Seventh+Edition&arch=default&format=html

 The environment for any simple-command may be augmented by prefixing it with one or more assignments to parameters. Thus these two lines are equivalent TERM=450 cmd args (export TERM; TERM=450; cmd args) 

Étant donné la command dans votre exemple, echo s'exécute, mais ce qui arrive à $APPLE est un peu plus compliqué.

Il est vrai, comme indiqué dans la réponse de @ Pasortingck, que si le shell invoque un process, toutes les variables déclarées sur la command line précédant son invocation sont spécifiées pour être exscopes dans son environnement. Et en outre, ces variables sont également spécifiées pour expirer avec le process invoqué – donc …

 unset var; var=val cmd; echo ${var-unset.} 

… devrait imprimer unset.

Mais là où tout ce concept devient un peu plus compliqué, et comme votre propre exemple le démontre, c'est à ce moment que cmd n'est pas un process invoqué mais plutôt une shell-builtin, une fonction shell ou un utilitaire embedded shell spécial. Dans chacun de ces trois cas, le shell exécutera probablement certaines de ses propres routines en memory et n'appellera rien du tout.

Par exemple, echo est presque définitivement un utilitaire embedded shell – comme la plupart des shells que je connais le fournissent en tant que tel – mais ce n'est pas une spécification spéciale spécifiée par POSIX. De cette façon, il s'agit essentiellement d'une fonction shell qui doit émuler un exécutable externe. Ceci est probablement énoncé un peu plus clairement ici:

Le terme "embedded" implique que le shell peut exécuter l'utilitaire directement et n'a pas besoin de le searchr. Une implémentation peut choisir de rendre un utilitaire embedded; Cependant, les utilitaires spéciaux décrits ici diffèrent des utilitaires embeddeds habituels …

Les assignations de variables spécifiées avec des utilitaires embeddeds spéciaux restnt en vigueur une fois l'intégration terminée; ceci ne doit pas être le cas avec un utilitaire standard embedded ou autre.

Les utilitaires spéciaux spéciaux de cette section n'ont pas besoin d'être fournis de manière accessible via la famille de fonctions exec définie dans le volume Interfaces système de POSIX.1-2008.

Ainsi, une variable déclarée sur la command line de echo périt avec echo , mais une déclaration déclarée sur la command line de l'set persiste (bien que bash par défaut ne respecte pas cette règle) . Il en est de même lorsque cmd est une fonction shell:

Lorsqu'une fonction est exécutée, elle doit avoir les propriétés d' erreur de syntaxe et d' assignation de variable décrites pour les utilitaires embeddeds spéciaux dans la list énumérée au début des utilitaires embeddeds spéciaux .