Kan vi använda bashs villkorliga operatör med tilldelningsoperatorer efter kolon?
Bash-referenshandbok förklarar aritmetiska operatorer enligt följande.
- villkorlig operator
expr ? expr : expr
- uppgift
= *= /= %= += -= <<= >>= &= ^= |=
Först verkar den här koden fungera bra:
a=1; ((a? b=1 : 2 )) #seems to work
Men när jag använder tilldelningsoperatörer efter :
, fick jag ”försök att tilldela till icke-variabelt” fel:
a=1; ((a? b=1 : c=1)) #attempted assignment to non-variable error
Varför kan vi bara använda tilldelningsoperatorer före kolon?
Kommentarer
Svar
Bash analyserar ditt senaste kommando som
a=1; (( (a? b=1 : c)=1 ))
vilket bör tydliggöra varför det inte fungerar. Istället måste du använda
a=1; (( a? b=1 : (c=1) ))
Svar
Detta kallas en ternary assignment
uttryck. Här ”är lite från ett annat av mina 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 ser, som du säger, detta är en villkorad tilldelningsoperation. Det beror på förhållandena. Syntaxen fungerar så här:
$((var = $condition <compare_operator> $condition \ ?if $true_assign :or $false_assign ))
Jag tror inte att du använder det här korrekt.
Från wikipedia :
?:
används enligt följande:
condition ? value_if_true : value_if_false
Villkoret utvärderas som sant eller falskt som ett booleskt uttryck. På grundval av utvärderingen av det booleska villkoret returnerar hela uttrycket value_if_true om villkoret är sant, men value_if_false annars. Vanligtvis måste de två deluttrycken value_if_true och value_if_false ha samma typ, som bestämmer typen av hela uttrycket. Vikten av denna typkontroll ligger i operatörens vanligaste användning – i villkorade tilldelningsuttalanden. I denna användning visas det som ett uttryck på höger sida av ett uppdragsuttalande, enligt följande:
variable = condition ? value_if_true : value_if_false
?:
-operatören liknar hur villkorliga uttryck (if-then-else
-konstruktioner) fungerar i funktionella programmeringsspråk, som Scheme, ML och Haskell, eftersom if-then-else bildar en uttryck istället för ett uttalande på dessa språk.
Jag tror att ditt specifika problem är relaterat till detta:
Som i if-else-konstruktionen utvärderas endast ett av uttrycken ”x” och ”y”.
Om du läser igenom länken ovan på ternary
uttryck du kommer att se den utvärderingen n är kortsluten så din uppgift på falska sidofelen eftersom 1 = true
.
I alla fall spelar det ingen roll för mycket eftersom jag inte tror att det här gör vad du tror det gör.
Svar
Ternära operatörer returnerar ett värde baserat på ett test. De används inte för förgrening.
Här är ett sätt att få en pseudo-ternär operatör för bash (notera back-fästingarna):
$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
ochbash
och de beter sig alla på samma sätt trots att de inte har specificerats av POSIX. Ditt exempel fungerar bara ibash
ochzsh
så vitt jag vet. Detta är dock POSIX-vänligt:( : ${a?} ) && b=1 || c=1
. Jag tycker också att det är mycket lättare att läsa änternary
eller ditt eget exempel.