Czy możemy użyć operatora warunkowego basha z operatorami przypisania po dwukropku?
Bash podręcznik referencyjny wyjaśnia następujące operatory arytmetyczne.
- operator warunkowy
expr ? expr : expr
- przypisanie
= *= /= %= += -= <<= >>= &= ^= |=
Po pierwsze, ten kod wydaje się działać dobrze:
a=1; ((a? b=1 : 2 )) #seems to work
Ale kiedy używam operatorów przypisania po :
, otrzymałem błąd „próbowano przypisać do wartości innej niż zmienna”:
a=1; ((a? b=1 : c=1)) #attempted assignment to non-variable error
Dlaczego przed dwukropkiem możemy używać tylko operatorów przypisania?
Komentarze
Odpowiedź
Bash analizuje Twoje ostatnie polecenie jako
a=1; (( (a? b=1 : c)=1 ))
, co powinno wyjaśnić, dlaczego nie działa. Zamiast tego musisz użyć
a=1; (( a? b=1 : (c=1) ))
Answer
To się nazywa ternary assignment
wyrażenie. Oto fragment z innej mojej odpowiedzi:
% 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
Jak mówisz, jest to operacja przypisania warunkowego . To zależy od warunków. Składnia wygląda następująco:
$((var = $condition <compare_operator> $condition \ ?if $true_assign :or $false_assign ))
Nie sądzę, że używasz tego poprawnie.
Od wikipedia :
?:
jest używany w następujący sposób:
condition ? value_if_true : value_if_false
Warunek jest oceniany jako prawda lub fałsz jako wyrażenie boolowskie. Na podstawie oceny warunku logicznego całe wyrażenie zwraca wartość_jeżeli_prawda, jeśli warunek jest prawdziwy, ale wartość_jeśli_fałsz w przeciwnym razie. Zwykle dwa wyrażenia podrzędne wartość_jeżeli_prawda i wartość_jeżeli_fałsz muszą mieć ten sam typ, który określa typ całego wyrażenia. Znaczenie tego sprawdzania typu leży w najczęstszym zastosowaniu operatora – w warunkowych instrukcjach przypisania. W tym przypadku pojawia się jako wyrażenie po prawej stronie instrukcji przypisania, w następujący sposób:
variable = condition ? value_if_true : value_if_false
?:
jest podobny do sposobu, w jaki wyrażenia warunkowe (konstrukcjeif-then-else
) działają w funkcjonalnych językach programowania, takich jak Scheme, ML i Haskell, ponieważ if-then-else tworzy wyrażenie zamiast instrukcji w tych językach.
Myślę, że twój konkretny problem jest związany z tym:
Tak jak w konstrukcji if-else tylko jedno z wyrażeń „x” i „y” jest oceniane.
Jeśli przeczytasz powyższy link na temat wyrażeń ternary
zobaczysz tę ocenę n jest zwarte, więc twoje przypisanie po fałszywej stronie błędów, ponieważ 1 = true
.
W każdym razie nie ma to znaczenia za dużo, ponieważ nie sądzę, że działa to tak, jak myślisz.
Odpowiedź
Operatory trójskładnikowe zwracają wartość na podstawie Badanie. Nie są używane do rozgałęziania.
Oto jeden ze sposobów uzyskania pseudo-potrójnego operatora dla bash (zwróć uwagę na znaki wstecz):
$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
operatory wdash, zsh, sh
ibash
i wszystkie zachowują się tak samo, mimo że nie są określone przez POSIX. Twój przykład działa tylko wbash
izsh
, o ile wiem. Jest to jednak zgodne z POSIX:( : ${a?} ) && b=1 || c=1
. Uważam też, że jest o wiele łatwiejszy do odczytania niżternary
lub własny przykład.