Expansion des paramètres
La réponse évidente est d'utiliser l'une des formes spéciales d'expansion des paramètres :
: ${STATE?"Need to set STATE"}
: ${DEST:?"Need to set DEST non-empty"}
Ou, mieux encore (voir la section "Position des guillemets" ci-dessous) :
: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"
La première variante (qui utilise uniquement ?
) exige que STATE soit défini, mais STATE="" (une chaîne vide) est acceptable - ce n'est pas exactement ce que vous voulez, mais c'est une notation alternative et plus ancienne.
La deuxième variante (utilisant :?
) exige que DEST soit défini et non vide.
Si vous ne fournissez pas de message, le shell fournit un message par défaut.
Le site ${var?}
construct est portable jusqu'à la version 7 d'UNIX et du Bourne Shell (1978 environ). Le site ${var:?}
La construction est légèrement plus récente : Je pense qu'elle était dans System III UNIX vers 1981, mais elle a pu être dans PWB UNIX avant cela. Elle se trouve donc dans le shell Korn, et dans les shells POSIX, dont spécifiquement Bash.
Il est généralement documenté dans la page de manuel du shell dans une section appelée Expansion des paramètres . Par exemple, le bash
le manuel dit :
${parameter:?word}
Afficher l'erreur si elle est nulle ou non définie. Si le paramètre est nul ou non défini, le développement de word (ou un message à cet effet si word n'est pas présent) est écrit dans l'erreur standard et le shell, s'il n'est pas interactif, quitte. Sinon, la valeur du paramètre est substituée.
La commande du côlon
Je devrais probablement ajouter que la commande colon voit simplement ses arguments évalués et qu'elle réussit. Il s'agit de la notation originale des commentaires du shell (avant ' #
à la fin de la ligne). Pendant longtemps, les scripts du shell Bourne avaient un deux-points comme premier caractère. Le shell C lisait un script et utilisait le premier caractère pour déterminer s'il était destiné au shell C (un ' #
) ou l'interpréteur de commandes Bourne (un hachage :
colon "). Ensuite, le noyau s'est mis de la partie et a ajouté le support de ' #!/path/to/program
' et le shell Bourne a obtenu ' #
et la convention des deux points a été abandonnée. Mais si vous rencontrez un script qui commence par un deux-points, vous savez maintenant pourquoi.
Position des guillemets
blong demandé dans un commentaire :
Des idées sur cette discussion ? https://github.com/koalaman/shellcheck/issues/380#issuecomment-145872749
L'essentiel de la discussion est le suivant :
Cependant, lorsque je shellcheck
(avec la version 0.4.1), je reçois ce message :
In script.sh line 13:
: ${FOO:?"The environment variable 'FOO' must be set and non-empty"}
^-- SC2086: Double quote to prevent globbing and word splitting.
Des conseils sur ce que je dois faire dans ce cas ?
La réponse courte est "faites comme shellcheck
suggère" :
: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"
Pour illustrer pourquoi, étudiez ce qui suit. Notez que le :
n'affiche pas ses arguments (mais l'interpréteur de commandes les évalue). Nous voulons voir les arguments, donc le code ci-dessous utilise la commande printf "%s\n"
à la place de :
.
$ mkdir junk
$ cd junk
$ > abc
$ > def
$ > ghi
$
$ x="*"
$ printf "%s\n" ${x:?You must set x} # Careless; not recommended
abc
def
ghi
$ unset x
$ printf "%s\n" ${x:?You must set x} # Careless; not recommended
bash: x: You must set x
$ printf "%s\n" "${x:?You must set x}" # Careful: should be used
bash: x: You must set x
$ x="*"
$ printf "%s\n" "${x:?You must set x}" # Careful: should be used
*
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
abc
def
ghi
$ x=
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
bash: x: You must set x
$ unset x
$ printf "%s\n" ${x:?"You must set x"} # Not quite careful enough
bash: x: You must set x
$
Notez comment la valeur dans $x
est étendu à la première *
et ensuite une liste de noms de fichiers lorsque l'expression globale n'est pas entre guillemets. C'est ainsi que shellcheck
recommande de réparer. Je n'ai pas vérifié qu'il n'y avait pas d'objection à la forme où l'expression est entre guillemets doubles, mais il est raisonnable de penser que c'est OK.
2 votes
Beaucoup de réponses à cette question ressemblent à quelque chose que vous verriez sur Code Golf Stack Exchange .