Lorsque vous déréférencez une variable dans bash
, vous devez utiliser le $
signe. Néanmoins, il semble que ce qui suit fonctionne très bien:
x=5
[[ x -gt 2 ]]
Quelqu'un peut-il expliquer cela?
Modifier: (plus d'informations)
Ce que je veux dire, c'est comment et pourquoi la commande [[]] déréférence ma variable x sans le signe $. Et oui, si x = 1, l'instruction est évaluée à false (retourne le statut 1)
bash
bash-expansion
Client
la source
la source
x=1
suiviez par[[ x -gt 2]]
?Réponses:
La raison en est que
-eq
force une évaluation arithmétique des arguments.Un opérateur arithmétique:
-eq
,-gt
,-lt
,-ge
,-le
et-ne
dans un[[ ]]
(ksh, zsh et bash) des moyens d'étendre automatiquement les noms de variables comme dans le langage C, pas besoin d'un chef de file$
.Pour confirmation, nous devons examiner le code source bash. Le manuel n'offre aucune confirmation directe .
A
test.c
l' intérieur du traitement des opérateurs arithmétiques tombent dans cette fonction:Où
s
ett
sont les deux opérandes. Les opérandes sont remis à cette fonction:La fonction
evalexp
est définie à l'intérieurexpr.c
, qui a cet en-tête:Donc, oui, les deux côtés d'un opérateur arithmétique entrent (directement) dans l'évaluation de l'expression arithmétique. Directement, pas de mais, pas de si.
En pratique, avec:
Ces deux échouent:
Ce qui est correct,
x
n'est pas développé etx
n'est pas égal à un nombre.Pourtant:
La variable nommée
x
est développée (même sans $).Cela ne se produit pas pour un
[…]
dans zsh ou bash (c'est le cas dans ksh).C'est la même chose que ce qui se passe à l'intérieur d'un
$((…))
:Et, veuillez comprendre que c'est (très) récursif (sauf en tiret et en yash):
A 😮
Et assez risqué:
L'erreur de syntaxe pourrait être facilement évitée:
Comme dit le proverbe: désinfectez votre entrée
fin de 😮
Les (plus anciens) externes
/usr/bin/test
(et non intégréstest
) et les plus anciens et également externesexpr
ne développent pas les expressions uniquement des entiers (et apparemment, uniquement des entiers décimaux):la source
[[
un mot-clé, les opérateurs et les opérandes sont détectés lorsque la commande est lue et non après l'expansion. Ainsi[[
peut traiter-eq
de manière plus intelligente que, par exemple,[
. Mais ce que je me demande, c'est: où peut-on trouver de la documentation sur les utilisations de logique bash pour interpréter les commandes composées? Cela ne me semble pas tout à fait évident et je ne suis apparemment pas en mesure de trouver des explications satisfaisantes dansman
ouinfo bash
.test
section man Les opérateurs arithmétiques zshbuiltins attendent des arguments entiers plutôt que des expressions arithmétiques . Ce qui confirme que certains arguments sont traités comme des expressions arithmétiques par le test intégré dans des conditions non spécifiées dans cette citation. Je vais confirmer avec le code source….…Les opérandes des comparaisons numériques
-eq
,-gt
,-lt
,-ge
,-le
et-ne
sont considérés comme des expressions arithmétiques. Avec une certaine limitation, ils doivent toujours être des mots à coque unique.Le comportement des noms de variables dans l'expression arithmétique est décrit dans Shell Arithmetic :
et aussi:
Mais je ne trouve pas réellement la partie de la documentation où il est dit que les comparaisons numériques prennent des expressions arithmétiques. Il n'est pas décrit dans Constructions conditionnelles sous
[[
, ni dans Bash Conditional Expressions .Mais, par expérience, cela semble fonctionner comme dit ci-dessus.
Donc, des trucs comme ça fonctionnent:
cela aussi (la valeur de la variable est évaluée):
Mais ce n'est pas le cas; ce n'est pas un seul mot shell quand le
[[ .. ]]
est analysé, donc il y a une erreur de syntaxe dans le conditionnel:Dans d'autres contextes arithmétiques, il n'est pas nécessaire que l'expression soit sans espace. Cela s'affiche
999
, car les crochets délimitent sans ambiguïté l'expression arithmétique dans l'index:D'un autre côté, la
=
comparaison est une correspondance de modèle , et n'implique pas d'arithmétique, ni l'expansion automatique de variable effectuée dans un contexte arithmétique (constructions conditionnelles):C'est donc faux puisque les chaînes sont évidemment différentes:
comme c'est le cas, même si les valeurs numériques sont les mêmes:
et ici aussi, les chaînes (
x
et6
) sont comparées, elles sont différentes:Cela étendrait la variable, cependant, c'est donc vrai:
la source
arg1 OP arg2
dit que les arguments peuvent être des entiers positifs ou négatifs, ce qui, je suppose, est supposé impliquer qu'ils sont traités comme des expressions arithmétiques. Confusément, cela implique également qu'ils ne peuvent pas être nuls. :)[
, et là, ce ne sont pas des expressions arithmétiques. Au lieu de cela, Bash se plaint de non-entiers.[
est une commande externe, elle n'a pas accès aux variables shell. Il est souvent optimisé avec une commande intégrée, mais il se comporte toujours de la même manière.[
aussi bien à[[
. Même avec[
, les opérandes to-eq
et friends sont / doivent être des entiers, de sorte que la description s'applique également. Prendre "doit être des entiers" pour signifier "sont interprétés comme des expressions arithmétiques" ne s'applique pas dans les deux cas. (Probablement au moins en partie en raison de se[
comporter comme une commande ordinaire, comme vous le dites.)Oui, votre observation est correcte, l'expansion des variables est effectuée sur les expressions entre crochets
[[ ]]
, vous n'avez donc pas besoin de mettre$
devant un nom de variable.Ceci est explicitement indiqué dans le
bash
manuel:Notez que ce n'est pas le cas de la version simple parenthèse
[ ]
, comme ce[
n'est pas un mot-clé shell (syntaxe), mais plutôt une commande (en bash il est intégré, d'autres shells pourraient utiliser externe, aligné pour tester).la source
(x=1; [[ $x = 1 ]]; echo $?)
retours0
,(x=1; [[ x = 1 ]]; echo $?)
retours1
, c'est-à-dire que l'expansion des paramètres n'est pas effectuéex
lorsque nous comparons des chaînes. Ce comportement ressemble à une évaluation arithmétique déclenchée par l'expansion arithmétique, c'est-à-dire ce qui se passe dans(x=1; echo $((x+1)))
. (À propos de l'évaluation arithmétique,man bash
indique que «dans une expression, les variables shell peuvent également être référencées par leur nom sans utiliser la syntaxe d'expansion des paramètres.)-gt
opérateur attend le nombre, l'expression entière est réévaluée comme si à l'intérieur(())
, d'autre part==
attend les chaînes, donc la fonction de filtrage est déclenchée. Je n'ai pas fouillé dans le code source, mais cela semble raisonnable.[
est un shell intégré à bash.