Une réponse StackOverflow avec> 3,5 K votes présente cette ligne unique pour l'attribution au DIR
répertoire du script bash actuel:
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
Je suis perplexe devant les guillemets imbriqués. Pour autant que je sache, les fragments suivants sont entre guillemets:
"$( cd "
"${BASH_SOURCE[0]}"
" && pwd )"
... et tout le reste à droite de =
(ie $( dirname
et )
) n'est pas cité. En d'autres termes, je suppose que les 2e, 4e et 6e "
caractères "ferment" respectivement les 1er, 3e et 5e "
caractères.
Je comprends à quoi servent les guillemets doubles "${BASH_SOURCE[0]}"
, mais à quoi servent les deux autres paires de guillemets doubles?
Si, en revanche (et malgré le score de vote élevé), l'extrait ci-dessus est incorrect, quelle est la bonne façon d'atteindre son objectif nominal?
(Par intention nominale, je veux dire: collecter la valeur retournée par pwd
après la première cd
entrée dans le répertoire retourné par dirname "${BASH_SOURCE[0]}"
, et effectuer la cd
-ing dans un sous-shell, de sorte que le $PWD
shell parent reste inchangé).
$( here, it's a subshell, but you are writing code as if you were writing it on the "first level" of the shell .... )
.lsb_dist="$(. /etc/os-release && echo "$ID")"; echo "$lsb_dist"
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
fonctionne également.Réponses:
Votre puzzle n'est pas juste sur la façon dont
bash
(et le shell en général) a analysé l'entrée. Dans:Tout d'abord,
bash
analysez le côté droit de l'affectation sur une longue chaîne$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
car les guillemets doubles peuvent apparaître à l'intérieur des guillemets doubles .Ensuite,
bash
commencez à analyser la substitution de commandes. Étant donné que tous les caractères qui suivent la parenthèse ouverte jusqu'aux parenthèses fermantes sont utilisés pour construire la commande à l'intérieur de la substitution de commande, vous obtiendrez:Le shell continue d'analyser cette commande composée, la divise en deux parties:
cd "$( dirname "${BASH_SOURCE[0]}" )"
Ensuite, appliquez la même règle d'analyse pour
cd "$( dirname "${BASH_SOURCE[0]}" )"
, mais cette fois, les guillemets doubles ne sont pas redondants, mais ont du sens. Ils empêchent le fractionnement de champ sur le résultat de$( dirname "${BASH_SOURCE[0]}" )
, et également l'expansion de${BASH_SOURCE[0]}
(Contrairement aux guillemets les plus externes, il nesplit+glob
sera pas nécessaire dans RHS d'attribuer des variables pour empêcher ).Cette règle s'applique à la substitution de commandes dans tous les shell POSIX . Un puzzle plus détaillé que vous pouvez lire dans la section Reconnaissance de jetons de la spécification POSIX .
la source
Une fois à l'intérieur
$(...)
, la citation recommence à zéro.En d'autres termes,
"..."
et$(...)
peuvent s'imbriquer les uns dans les autres. La substitution de processus$(...)
, peut contenir une ou plusieurs chaînes complètes entre guillemets. En outre, les chaînes entre guillemets doubles peuvent contenir une ou plusieurs substitutions de processus complètes . Mais, ils ne s'entrelacent pas. Ainsi, une chaîne entre guillemets doubles qui commence à l'intérieur d'une substitution de processus ne s'étendra jamais à l'extérieur de celle-ci ou vice versa.Considérez donc:
L'intérieur
$(...)
est:Dans ce qui précède,
${BASH_SOURCE[0]}
on cite deux fois. Toutes les citations, doubles ou simples, en dehors de la ne$(...)
sont pas pertinentes pour déterminer que les${BASH_SOURCE[0]}
guillemets sont doubles.L'extérieur
$(...)
contient:Ici, l'expression
$( dirname "${BASH_SOURCE[0]}" )
est mise entre guillemets. Le fait qu'il y ait des guillemets à l'extérieur de l'extérieur$(...)
n'est pas pertinent lorsque l'on considère ce qui est à l'intérieur. Le fait qu'il y ait des citations à l'intérieur$(...)
n'est pas non plus pertinent.Voici comment les guillemets doubles correspondent:
la source
irrelevant
? À l'exception de la plupart des parenthèses extérieures, toutes les autres ont leur propre signification.$(...)
lie plus fort que"..."
» n'a pas de sens. Ce ne sont pas des opérateurs d'infixe, et il n'y a pas de hiérarchie entre eux (s'il y en avait, cela signifierait que les guillemets ne peuvent pas être entre parenthèses ou les parenthèses ne peuvent pas être entre guillemets, mais ce n'est pas le cas). Le terme technique est cela$(…)
et"…"
nid.