Sur frêne, tiret et bash, quand je cours
$ echo ab$
il revient
ab$
Ce comportement est-il spécifié par POSIX ou s'agit-il simplement d'une convention courante dans les shells compatibles POSIX? Je n'ai rien trouvé sur la page Langage de commande du shell POSIX qui mentionne ce comportement.
$
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).ab$
, il n'y a pas de caractère suivant$
, qu'il ait été "suivi" par un caractère nul dans la chaîne d'entrée d'origine ou un espace dans un cas commeecho ab$ foo
; l'espace blanc non cité d'origine a été reconnu et supprimé après l'analyse.Réponses:
$
n'a pas de signification particulière en soi (essayezecho $
), uniquement lorsqu'il est combiné avec un autre caractère après lui et formant une expansion, par exemple$var
(ou${var}
)$(util)
,,$((1+2))
.Le
$
obtient sa signification "spéciale" en définissant une extension dans la norme POSIX sous la section Reconnaissance de jetons :Donc, si
$
ne forme pas une expansion, d'autres règles d'analyse entrent en vigueur:Cela couvre votre
ab$
chaîne.Dans le cas d'un seul
$
(le «nouveau mot» serait le$
seul):La signification du mot généré contenant un
$
qui n'est pas une extension standard est explicitement définie comme non spécifiée par POSIX.Notez également qu'il
$
s'agit du dernier caractère$$
, mais qu'il s'agit également de la variable qui contient le PID du shell actuel. Dansbash
,!$
peut invoquer une expansion d'historique (le dernier argument de la commande précédente). Donc, en général, non,$
n'est pas sans signification à la fin d'un mot non cité, mais à la fin d'un mot, cela ne signifie pas du moins une expansion standard.la source
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$
etecho $
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 :
"Non spécifié" est un terme particulier qui signifie ici que
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 unb
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éeecho a$ b
: sortie littérale, entièrement spécifiéeecho a$ b$
: sortie littérale, entièrement spécifiéeecho a$b
: expansion du paramètreb
, 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 à laecho
commande dans le cadre de son argument. Il s'agit d'une exigence de conformité sur le shell.la source
echo $
également littéral et entièrement spécifié?echo "$"
etecho "a b$"
tomber?