Kan vi bruge bashs betingede operator med tildelingsoperatorer efter kolon?
Bash-referencehåndbog forklarer aritmetiske operatorer som følger.
- betinget operator
expr ? expr : expr
- tildeling
= *= /= %= += -= <<= >>= &= ^= |=
Først ser denne kode ud til at fungere godt:
a=1; ((a? b=1 : 2 )) #seems to work
Men når jeg bruger tildelingsoperatører efter :
, fik jeg “forsøgt at tildele til ikke-variabel” -fejl:
a=1; ((a? b=1 : c=1)) #attempted assignment to non-variable error
Hvorfor kan vi kun bruge tildelingsoperatorer før kolon?
Kommentarer
Svar
Bash analyserer din sidste kommando som
a=1; (( (a? b=1 : c)=1 ))
, hvilket skulle gøre det klart, hvorfor det ikke fungerer. I stedet skal du bruge
a=1; (( a? b=1 : (c=1) ))
Svar
Dette kaldes en ternary assignment
udtryk. Her “er lidt fra et andet af mine svar:
% 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
Du kan se, som du siger, dette er en betinget tildelingshandling. Det afhænger af forholdene. Syntaksen fungerer således:
$((var = $condition <compare_operator> $condition \ ?if $true_assign :or $false_assign ))
Jeg tror ikke, du bruger dette korrekt.
Fra wikipedia :
?:
som følger:
condition ? value_if_true : value_if_false
Betingelsen evalueres som sand eller falsk som et boolsk udtryk. På basis af evalueringen af den boolske tilstand returnerer hele udtrykket værdi_om_ sandt, hvis betingelsen er sand, men ellers værdi_om_falsk. Normalt skal de to underudtryk value_if_true og value_if_false have samme type, der bestemmer typen for hele udtrykket. Vigtigheden af denne typekontrol ligger i operatørens mest almindelige anvendelse – i betingede tildelingserklæringer. I denne brug vises det som et udtryk i højre side af en opgaveerklæring som følger:
variable = condition ? value_if_true : value_if_false
?:
-operatøren ligner den måde, hvorpå betingede udtryk (if-then-else
-konstruktioner) fungerer i funktionelle programmeringssprog, som Scheme, ML og Haskell, da if-then-else danner en udtryk i stedet for en erklæring på disse sprog.
Jeg tror, at dit specifikke problem er relateret til dette:
Som i if-else-konstruktionen evalueres kun et af udtrykkene “x” og “y”.
Hvis du læser gennem ovenstående link på ternary
udtryk du vil se den evaluering n er kortsluttet, så din opgave på falske sidefejlene, fordi 1 = true
.
Under alle omstændigheder betyder det ikke noget for meget, fordi jeg ikke tror, det gør, hvad du synes, det gør.
Svar
Ternære operatører returnerer en værdi baseret på en test. De bruges ikke til forgrening.
Her er en måde at få en pseudo-ternær operatør til bash (bemærk back-ticks):
$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
operatører idash, zsh, sh
ogbash
, og de opfører sig alle ens, til trods for at de ikke er specificeret af POSIX. Dit eksempel fungerer kun ibash
ogzsh
så vidt jeg ved. Dette er dog POSIX-venligt:( : ${a?} ) && b=1 || c=1
. Jeg finder det også meget lettere at læse end ententernary
eller dit eget eksempel.