Selon la situation exacte, cela n'est pas explicitement spécifié (les implémentations peuvent donc faire ce qu'elles veulent) ou doit se produire comme vous l'avez observé. Dans votre scénario exact echo ab$
, POSIX rend obligatoire la sortie "ab $" que vous avez observée et elle n'est pas non spécifiée . Un résumé rapide de tous les différents cas est à la fin.
Il y a deux éléments: d'abord la tokenisation en mots, puis l'interprétation de ces mots.
Tokenisation
Tokenisation POSIX exige un $
qui ne soit pas le début d'une valide expansion de paramètres , la substitution de commande , ou substitution arithmétique pour être considéré comme une partie littérale de l' WORD
être construit jeton. En effet, la règle 5 ("Si le caractère actuel est un $
ou non guillemets `
, le shell doit identifier le début de tout candidat pour l'expansion des paramètres, la substitution de commandes ou l'expansion arithmétique à partir de leurs séquences de caractères non entre guillemets d'introduction: $
ou ${
, $(
ou `
, et $((
, respectivement" ) ne s'applique pas, car aucune de ces extensions n'y est viable. L'extension des paramètres nécessite qu'un nom valide y apparaisse et qu'un nom vide ne soit pas valide.
Étant donné que cette règle ne s'appliquait pas, nous continuons de suivre jusqu'à ce que nous en trouvions une qui s'applique. Les deux candidats sont # 8 ("Si le caractère précédent faisait partie d'un mot, le caractère actuel doit être ajouté à ce mot.") Et # 10 ("Le caractère actuel est utilisé comme début d'un nouveau mot.") , qui s'appliquent à echo a$
et echo $
respectivement.
Il y a aussi un troisième cas de la forme echo a$+b
qui tombe dans la même fissure, car ce +
n'est pas le nom d'un paramètre spécial. Nous y reviendrons plus tard, car il déclenche différentes parties des règles.
La spécification requiert donc que le $
soit considéré comme une partie du mot syntaxiquement, et il peut ensuite être traité ultérieurement.
Expansion des mots
Une fois que l'entrée a été analysée de cette manière, avec le $
mot inclus, des extensions de mot sont appliquées à chacun des mots qui ont été lus. Chaque mot est traité individuellement .
Il est précisé que :
Si un «$» non cité est suivi d'un caractère qui n'est pas l'un des suivants:
- Un caractère numérique
- Le nom de l'un des paramètres spéciaux (voir Paramètres spéciaux )
- Un premier caractère valide d'un nom de variable
- A
<left-curly-bracket>
('{')
- UNE
<left-parenthesis>
le résultat n'est pas spécifié.
"Non spécifié" est un terme particulier qui signifie ici que
- Un shell conforme peut choisir n'importe quel comportement dans ce cas
- Une application conforme ne peut pas s'appuyer sur un comportement particulier
Dans votre exemple, echo ab$
le $
n'est suivi d' aucun caractère , donc cette règle ne s'applique pas et le résultat non spécifié n'est pas appelé. Il n'y a tout simplement aucune expansion$
, donc il est littéralement présent et imprimé.
Lorsqu'il s'appliquer est dans notre troisième cas d' en haut . Ici est suivie , ce qui est un numéro, paramètre spécial ( , , , , , , , ou ), début d'une variable nom (ou un underscore alphabétique de l' ensemble portable de caractères ), ou l' un des supports. Dans ce cas, le comportement n'est pas spécifié: un shell conforme est autorisé à inventer un paramètre spécial appelé pour se développer , et une application conforme ne doit pas supposer que le shell ne le fait pas . Le shell peut également faire tout ce qu'il souhaite, y compris signaler une erreur.echo a$+b
$
+
@
*
#
?
-
$
!
0
+
Par exemple, zsh, y compris dans son mode POSIX, interprète $+b
comme "est un b
ensemble de variables " et remplace 1 ou 0 à sa place. Il a également des extensions pour ~
et =
. Il s'agit d'un comportement conforme.
Un autre endroit où cela pourrait se produire est echo "a$ b"
. Encore une fois, le shell est autorisé à faire ce qu'il veut, et vous, en tant qu'auteur du script, devez échapper au $
si vous voulez une sortie littérale. Si vous ne le faites pas, cela peut fonctionner, mais vous ne pouvez pas vous y fier. Il s'agit de la lettre absolue de la spécification, mais je ne pense pas que ce type de granularité ait été prévu ou envisagé.
En résumé
echo ab$
: sortie littérale, entièrement spécifiée
echo a$ b
: sortie littérale, entièrement spécifiée
echo a$ b$
: sortie littérale, entièrement spécifiée
echo a$b
: expansion du paramètre b
, entièrement spécifié
echo a$-b
: extension du paramètre spécial -
, entièrement spécifié
echo a$+b
: comportement non spécifié
echo "a$ b"
: comportement non spécifié
Pour un $
à la fin d'un mot, vous êtes autorisé à vous fier au comportement et il doit être traité littéralement et transmis à la echo
commande dans le cadre de son argument. Il s'agit d'une exigence de conformité sur le shell.
$
gagne- t-il une signification spéciale s'il s'agit du dernier caractère d'un mot?" Il n'y a pas de signification particulière unique attribuée à$
; il est utilisé pour introduire des extensions multiples, mais distinctes, comme l'expansion des paramètres${...}
, la substitution de commandes$(...)
et les expressions arithmétiques$((...))
. Certains shells introduisent des contextes supplémentaires, commeksh
la variante de substitution de commandes dex=${ echo foo; echo bar;}
(qui diffère de la norme$(...)
en n'exécutant pas les commandes dans un sous-shell).