751 Stimmen

Ternärer Operator (?:) in Bash

Gibt es eine Möglichkeit, so etwas zu tun

int a = (b == 5) ? c : d;

mit Bash?

1 Stimmen

@dutCh's Antwort zeigt, dass bash tatsächlich etwas Ähnliches wie den "ternären Operator" hat, jedoch wird dies in bash als "konditionaler Operator" expr?expr:expr bezeichnet (siehe man bash Abschnitt "Arithmetische Auswertung"). Beachten Sie, dass der bash "konditionale Operator" knifflig ist und einige Fallstricke hat.

0 Stimmen

Bash verfügt über einen ternären Operator für ganze Zahlen und er funktioniert innerhalb des arithmetischen Ausdrucks ((...)). Siehe Shell-Arithmetik.

2 Stimmen

Genau wie @codeforester erwähnt hat, funktioniert der ternäre Operator mit arithmetischer Expansion $(( )) und arithmetischer Auswertung (( )). Siehe auch https://mywiki.wooledge.org/ArithmeticExpression.

766voto

ghostdog74 Punkte 305138

Ternäroperator ? : ist nur eine verkürzte Form von wenn/dann/sonst

case "$b" in
 5) a=$c ;;
 *) a=$d ;;
esac

Oder

 [[ $b = 5 ]] && a="$c" || a="$d"

138 Stimmen

Beachten Sie, dass der = Operator auf die Zeichenfolgen-Gleichheit prüft, nicht auf numerische Gleichheit (d.h. [[ 05 = 5 ]] ist falsch). Wenn Sie eine numerische Vergleich verwenden möchten, benutzen Sie stattdessen -eq.

14 Stimmen

Es handelt sich eher um eine Kurzform für if/then/else

17 Stimmen

Es ist eine geniale Möglichkeit, das Kurzschlussverhalten zu nutzen, um einen ternären Operator-Effekt zu erzielen :) :) :)

605voto

Vladimir Punkte 9083

Code:

a=$([ "$b" == 5 ] && echo "$c" || echo "$d")

83 Stimmen

Dies ist besser als die anderen... Der Punkt beim ternären Operator ist, dass es sich um einen Operator handelt, daher befindet er sich in einem Ausdruck, daher muss er einen Wert zurückgeben.

2 Stimmen

Dies ist der prägnanteste Weg. Beachten Sie, dass, wenn der Teil mit echo "$c" ein mehrzeiliger Befehl mit Alias (wie echo 1; echo 2) ist, sollten Sie ihn in Klammern setzen.

2 Stimmen

Dies wird auch jede Ausgabe des getesteten Befehls erfassen (ja, in diesem speziellen Fall "wissen" wir, dass er keine erzeugt).

258voto

JWL Punkte 12479

Wenn die Bedingung nur überprüft, ob eine Variable gesetzt ist, gibt es sogar eine kürzere Form:

a=${VAR:-20}

weist a den Wert von VAR zu, wenn VAR gesetzt ist, ansonsten weist es ihm den Standardwert 20 zu - dies kann auch ein Ergebnis eines Ausdrucks sein.

Dieser Ansatz wird technisch als "Parameter Expansion" bezeichnet.

11 Stimmen

Im Fall der Übergabe eines Zeichenfolgenparameters mit Bindestrichen musste ich Anführungszeichen verwenden: a=${1:-'my-hyphenated-text'}

6 Stimmen

Link für die Faulen - es gibt zusätzliche Operatoren als nur den Ersatz (:-)

26 Stimmen

@JustinWrobel - leider keine Syntax wie ${VAR:-yes:-no}.

141voto

ivan_pozdeev Punkte 30938
if [[ $b -eq 5 ]]; then a="$c"; else a="$d"; fi

Der in anderen Antworten vorgeschlagene Ausdruck cond && op1 || op2 hat einen inhärenten Fehler: Wenn op1 einen Exit-Status ungleich Null hat, wird op2 stillschweigend das Ergebnis; der Fehler wird auch im Modus -e nicht erfasst. Daher ist dieser Ausdruck nur sicher zu verwenden, wenn op1 niemals fehlschlagen kann (z. B. :, true, wenn ein integrierter Befehl, oder eine Variablzuweisung ohne Operationen, die fehlschlagen können (wie Division und OS-Aufrufe)).

Beachten Sie die "" Anführungszeichen. Sie verhindern die Umwandlung aller Leerzeichen in einzelne Leerzeichen.

Doppelte eckige Klammern im Gegensatz zu einzelnen verhindern eine falsche Operation, wenn $b gleich einem Test-Operator ist (z. B. "-z"; ein Workaround mit [ ist [ "x$b" == "xyes" ] und funktioniert nur für Zeichenkettenvergleiche); sie heben auch die Anforderung zum Quoting auf.

0 Stimmen

Toller Punkt! Ich würde nur hinzufügen, dass dies genau die Art von hinterhältigem Fehler ist, den ShellCheck für Sie findet. In diesem Fall die entsprechende Wiki-Seite.

62voto

dutCh Punkte 557
(( a = b==5 ? c : d )) # Zeichenfolge + numerisch

48 Stimmen

Das ist gut für numerische Vergleiche und Zuweisungen, aber es liefert unberechenbare Ergebnisse, wenn man es für Zeichenfolgenvergleiche und Zuweisungen verwendet.... (( )) behandelt alle Zeichenfolgen als 0

12 Stimmen

Dies kann auch geschrieben werden: a=$(( b==5 ? c : d ))

0 Stimmen

Sie könnten in Betracht ziehen, bash Integer-Variable zu benutzen! Ihre Antwort wird zitiert.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X