Bash ' s bedingter Operator und Zuweisung

Können wir den bedingten Operator von bash mit Zuweisungsoperatoren nach dem Doppelpunkt verwenden?

Bash-Referenzhandbuch erläutert die arithmetischen Operatoren wie folgt.

  • Bedingter Operator expr ? expr : expr
  • Zuweisung = *= /= %= += -= <<= >>= &= ^= |=

Erstens scheint dieser Code gut zu funktionieren:

a=1; ((a? b=1 : 2 )) #seems to work 

Wenn ich jedoch nach : Zuweisungsoperatoren verwende, wurde der Fehler „Zuweisung versucht, nicht variabel“:

a=1; ((a? b=1 : c=1)) #attempted assignment to non-variable error 

Warum können wir nur Zuweisungsoperatoren vor dem Doppelpunkt verwenden?

Kommentare

  • Es mag Spaß machen, Variablenzuweisungen mit dem bedingten Operator durchzuführen, aber ' würde Ihren Code sehr unlesbar machen. Ich ' würde ((a)) && b=1 || c=1
  • @devnull Ich denke, der Code hängt am meisten davon ab, wer sie liest. Es mag zwar wahr sein, was Sie sagen, aber ich ' habe ternary -Operatoren in dash, zsh, sh und bash und alle verhalten sich gleich, obwohl sie nicht von POSIX angegeben wurden. Ihr Beispiel funktioniert meines Wissens nur in bash und zsh. Dies ist jedoch POSIX-freundlich: ( : ${a?} ) && b=1 || c=1. Ich finde es auch viel einfacher zu lesen als entweder ternary oder Ihr eigenes Beispiel.

Antwort

Bash analysiert Ihren letzten Befehl als

a=1; (( (a? b=1 : c)=1 )) 

, was klarstellen sollte, warum er nicht funktioniert. Stattdessen müssen Sie

a=1; (( a? b=1 : (c=1) )) 

Antwort

verwenden. Dies wird als ternary assignment Ausdruck. Hier „ein bisschen von einer anderen Antwort von mir:

% 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 

Sie sehen, wie Sie sagen, dies ist eine bedingte Zuweisungsoperation. Dies hängt von den Bedingungen ab. Die Syntax funktioniert folgendermaßen:

$((var = $condition <compare_operator> $condition \ ?if $true_assign :or $false_assign )) 

Ich glaube nicht, dass Sie dies richtig verwenden.

Von wikipedia :

?: wird verwendet wie folgt:

condition ? value_if_true : value_if_false

Die Bedingung wird als boolescher Ausdruck als wahr oder falsch bewertet. Auf der Grundlage der Auswertung der Booleschen Bedingung gibt der gesamte Ausdruck value_if_true zurück, wenn die Bedingung wahr ist, andernfalls value_if_false. Normalerweise müssen die beiden Unterausdrücke value_if_true und value_if_false denselben Typ haben, der den Typ des gesamten Ausdrucks bestimmt. Die Bedeutung dieser Typprüfung liegt in der häufigsten Verwendung des Operators – in bedingten Zuweisungsanweisungen. In dieser Verwendung wird sie wie folgt als Ausdruck auf der rechten Seite einer Zuweisungsanweisung angezeigt:

variable = condition ? value_if_true : value_if_false

Die ähnelt der Funktionsweise von bedingten Ausdrücken (if-then-else -Konstrukte) in funktionalen Programmiersprachen wie Scheme, ML und Haskell, da if-then-else eine bildet Ausdruck anstelle einer Anweisung in diesen Sprachen.

Ich denke, Ihr spezifisches Problem hängt damit zusammen:

Wie im if-else-Konstrukt wird nur einer der Ausdrücke „x“ und „y“ ausgewertet.

Wenn Sie den obigen Link zu ternary -Ausdrücken lesen Sie werden diese Bewertung sehen n ist kurzgeschlossen, daher ist Ihre Zuordnung auf der false -Seite fehlerhaft, weil 1 = true.

In jedem Fall spielt es keine Rolle zu viel, weil ich nicht glaube, dass dies das tut, was Sie denken.

Antwort

Ternäre Operatoren geben einen Wert zurück, der auf basiert ein Test. Sie werden nicht zum Verzweigen verwendet.

Hier ist eine Möglichkeit, einen pseudo-ternären Operator für Bash zu erhalten (beachten Sie die 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

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.