Pouvons-nous utiliser lopérateur conditionnel de bash avec des opérateurs daffectation après deux-points?
Le manuel de référence Bash explique les opérateurs arithmétiques comme suit.
- opérateur conditionnel
expr ? expr : expr
- affectation
= *= /= %= += -= <<= >>= &= ^= |=
Premièrement, ce code semble bien fonctionner:
a=1; ((a? b=1 : 2 )) #seems to work
Mais lorsque jutilise des opérateurs daffectation après :
, jobtiens lerreur « tentative daffectation à une non-variable »:
a=1; ((a? b=1 : c=1)) #attempted assignment to non-variable error
Pourquoi ne pouvons-nous utiliser que des opérateurs daffectation avant les deux points?
Commentaires
Réponse
Bash analyse votre dernière commande comme
a=1; (( (a? b=1 : c)=1 ))
ce qui devrait expliquer pourquoi cela ne fonctionne pas. À la place, vous devez utiliser
a=1; (( a? b=1 : (c=1) ))
Answer
Cela sappelle un ternary assignment
expression. Voici « un peu dune autre de mes réponses:
% a=abc % b=abcd % t=10 ; f=5 % echo $((r=${#a}>${#b}?t:f)) ; echo $r > 5 > 5 % echo $((r=${#a}<${#b}?t:f)) ; echo $r > 10 > 10
Vous voyez, comme vous le dites, cest une opération daffectation conditionnelle . Cela dépend des conditions. La syntaxe fonctionne comme ceci:
$((var = $condition <compare_operator> $condition \ ?if $true_assign :or $false_assign ))
Je ne pense pas que vous lutilisez correctement.
De wikipedia :
?:
est utilisé comme suit:
condition ? value_if_true : value_if_false
La condition est évaluée vraie ou fausse en tant quexpression booléenne. Sur la base de lévaluation de la condition booléenne, lexpression entière renvoie value_if_true si la condition est vraie, mais value_if_false sinon. Habituellement, les deux sous-expressions value_if_true et value_if_false doivent avoir le même type, qui détermine le type de lexpression entière. L’importance de cette vérification de type réside dans l’utilisation la plus courante de l’opérateur – dans les instructions d’affectation conditionnelle. Dans cet usage, elle apparaît comme une expression à droite d’une instruction d’affectation, comme suit:
variable = condition ? value_if_true : value_if_false
Le est similaire à la manière dont les expressions conditionnelles (constructions
if-then-else
) fonctionnent dans les langages de programmation fonctionnels, comme Scheme, ML et Haskell, car if-then-else forme un expression au lieu dune déclaration dans ces langues.
Je pense que votre problème spécifique est lié à ceci:
Comme dans la construction if-else, une seule des expressions « x » et « y » est évaluée.
Si vous lisez le lien ci-dessus sur les expressions ternary
vous verrez cette évaluation n est court-circuité donc votre affectation du côté faux erreurs car 1 = true
.
Dans tous les cas, cela na pas dimportance trop parce que je ne pense pas que cela fait ce que vous pensez.
Réponse
Les opérateurs ternaires renvoient une valeur basée sur un examen. Ils ne sont pas utilisés pour le branchement.
Voici une façon dobtenir un opérateur pseudo-ternaire pour bash (notez les rétrogradations):
$result=`[ < condition > ] && echo "true-result" || echo "false-result" `
$ a=
$ c=`[ $a ] && echo 1 || echo 0`
$ echo $c
0
$ a=5
$ c=`[ $a ] && echo 1 || echo 0`
$ echo $c
1
((a)) && b=1 || c=1
ternary
opérateurs dansdash, zsh, sh
, etbash
et ils se comportent tous de la même manière, bien quils ne soient pas spécifiés par POSIX. Votre exemple ne fonctionne que dansbash
etzsh
pour autant que je sache. Cependant, ceci est compatible avec POSIX:( : ${a?} ) && b=1 || c=1
. Je le trouve aussi beaucoup plus facile à lire queternary
ou votre propre exemple.