Opérateur conditionnel et affectation de Bash '

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

  • Il peut être amusant d’affecter des variables à l’aide de l’opérateur conditionnel, mais ' rend votre code hautement illisible. Je ' je préfère ((a)) && b=1 || c=1
  • @devnull Je pense que le code dépend surtout de celui qui le lit. Néanmoins, ce que vous dites est peut-être vrai, mais jai ' testé ternary opérateurs dans dash, zsh, sh, et bash 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 dans bash et zsh pour autant que je sache. Cependant, ceci est compatible avec POSIX: ( : ${a?} ) && b=1 || c=1. Je le trouve aussi beaucoup plus facile à lire que ternary ou votre propre exemple.

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

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *