La syntaxe de «$ {PS1-}» est-elle valide et en quoi diffère-t-elle du simple «$ PS1»?

12

Je regarde un script qui a:

if [ "${PS1-}" ]; then

Cela -me dérange un peu parce qu'il ne semble pas avoir la syntaxe standard Posix ou Bash. Est-ce une syntaxe mystérieuse qui existe depuis toujours, ou est-ce une faute de frappe? Toute référence à des normes / documents serait appréciée.

Normalement, je le coderais:

if [ "$PS1" ]; then

Qu'est-ce qui est plus correct ou y a-t-il une différence entre eux?

Gregor
la source

Réponses:

12

Il s'agit certainement de la syntaxe POSIX . Paraphraser:

Utilisation ${parameter-word}, si parameterest

  • définir et non nul, puis remplacer la valeur de parameter,
  • définir mais null, puis remplacer null, et
  • non défini, puis remplacer word.

Exemple de session:

$ echo "${parameter-word}"
word
$ parameter=
$ echo "${parameter-word}"

$ parameter=value
$ echo "${parameter-word}"
value

"Null" signifie simplement la chaîne vide. Il n'y a pas de valeur nulle spéciale dans les shells POSIX, contrairement à SQL, par exemple.

Ceci est également documenté dans la section "Extension des paramètres" de man bash.

l0b0
la source
1
Je suppose que les pages de manuel bash et dash sont incomplètes, car elles ne mentionnent pas cette syntaxe (impaire)!
Gregor
1
@Gregor Les deux manuels le mentionnent. Dans le manuel Bash, c'est dans le paragraphe avant la liste des extensions de paramètres, et dans le manuel Dash, c'est dans le paragraphe après.
Kusalananda
1
OK, "Omettre les deux points ...." Je n'ai pas vu ça :(
Gregor
zshest le seul shell que je connaisse qui mentionne explicitement les variantes sans colon, plutôt que de simplement noter ce que fait l'omission du colon.
chepner
1
@pts, le texte de POSIX utilise presque exclusivement le terme "null", ce qui pourrait expliquer son utilisation dans les pages de manuel.
ilkkachu
23

L'expansion variable ${parameter:-word}utilisera la valeur de $parametersi elle est définie et non nulle (pas une chaîne vide), sinon elle utilisera la chaîne word.

L'omission de :ne testera pas si la valeur est vide, seulement si elle n'est pas définie ou non.

Cela signifie que ${PS1-}sera étendu à la valeur de $PS1si elle est définie, mais à une chaîne vide si elle est vide ou non définie. Dans ce cas, c'est exactement le même que ${PS1:-}que la chaîne après -est vide aussi.

La différence entre "${PS1-}"et "$PS1"est subtile, comme le note @Rakesh Sharma: les deux se développeront à la valeur de $PS1, ou à une chaîne vide si elle n'est pas définie. L'exception est quand set -uest actif, auquel cas l'expansion des variables non définies entraînerait une erreur . La valeur par défaut (vide) définie par "${PS1-}"contourne cela, étendant un non défini PS1à la chaîne vide sans erreur.

Il s'agit d'une syntaxe standard ( originaire du shell Bourne à la fin des années 70 ), tout comme quelques autres extensions similaires.

Kusalananda
la source
Et comme il a été cité, c'est la même chose "$PS1", car si PS1est vide, il est vide et les guillemets empêchent le mot de disparaître complètement.
ilkkachu
4
Tant que le set -un'est pas en vigueur. Lorsque l'option nounset est activée, "$ PS1" => donne une erreur. "$ {PS-}" ne le fera pas.
@RakeshSharma c'est un bon point. La syntaxe différente peut en fait donner des résultats différents en fonction de l'option nounset, donc le test ["$ {parameter-}"] est probablement plus correct!
Gregor
1
@Kusalananda: Veuillez noter que ${parameter:-word}va utiliser la valeur de $parametersi elle est NON NULL. Dans tous les autres cas (ce qui signifie: soit défini mais NULL ou non défini), il sera utilisé word. Votre formulation:if its set or null
@ikkachu: Oui, c'est exact. Seulement lorsque les variables sont set AND nonnull=> utiliser elles-mêmes. Sinon, ( set but NULL OR unset) => utiliser le mot.
6

La syntaxe:

${parameter:-word}

et un formulaire spécial:

${parameter-word}

est la syntaxe valide dans le shell POSIX , signifie utiliser la valeur par défaut wordsi parameterest non défini ou nul.


Normalement, avec wordest vide, alors:

${parameter-}

et:

$parameter

ou:

${parameter}

sont équivalents.

Mais sous l'effet de set -u, toutes les variables non définies entraînent la fermeture du shell. ${parameter-}est utilisé pour contourner cette règle stricte. Cela fonctionne dans les deux cas, donc oui, c'est plus correct.

cuonglm
la source