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.

11voto

Brad Parks Punkte 59613

Das Folgende scheint für meine Anwendungsfälle zu funktionieren:

Beispiele

$ tern 1 YES NO                                                                             
YES

$ tern 0 YES NO                                                                             
NO

$ tern 52 YES NO                                                                            
YES

$ tern 52 YES NO 52                                                                         
NO

und kann in einem Skript wie folgt verwendet werden:

ERGEBNIS=$(tern 1 YES NO)
echo "Das Ergebnis ist $ERGEBNIS"

tern

#!/usr/bin/env bash

function show_help()
{
  ME=$(basename "$0")
  IT=$(cat < 0
FALSE_VALUE=${4:-0}

function main
{
if [ "$1" == "$FALSE_VALUE" ] || [ "$1" = '' ]; then
echo $3
exit;
fi;

echo $2
}

main "$1" "$2" "$3"

10 Stimmen

Sehr erklärend. Sehr umfassend. Sehr ausführlich. Drei Dinge, die mir gefallen. ;-)

3 Stimmen

Ist tern Teil von Bash? Mac scheint es nicht zu haben.

5 Stimmen

Hey @ - das ist der Name des Bash-Skripts - speichern Sie diesen "tern"-Abschnitt oben in einer Datei namens "tern" und führen Sie chmod 700 tern im selben Ordner aus. Jetzt haben Sie einen tern-Befehl in Ihrem Terminal.

8voto

Stefan Haberl Punkte 8595

Hier ist eine allgemeine Lösung, die

  • auch mit String-Tests funktioniert
  • sich eher wie ein Ausdruck anfühlt
  • alle subtilen Nebenwirkungen vermeidet, wenn die Bedingung fehlschlägt

Test mit numerischem Vergleich

a=$(if [ "$b" -eq 5 ]; then echo "$c"; else echo "$d"; fi)

Test mit String-Vergleich

a=$(if [ "$b" = "5" ]; then echo "$c"; else echo "$d"; fi)

5voto

wibble Punkte 595
(ping -c1 localhost&>/dev/null) && { echo "true"; } || {  echo "false"; }

0 Stimmen

Diese Lösung hat denselben Mangel, den ivan_pozdeev beschreibt, nämlich dass bei dieser Lösung echo "false" auftreten kann, wenn ping erfolgreich ist, aber aus irgendeinem Grund, wie unwahrscheinlich auch immer, der Teil echo "true" einen nicht-nullen Exit-Status zurückgibt (siehe ShellCheck SC2015). Um echo "false" nur dann auszugeben, wenn ping fehlschlägt, unabhängig vom Exit-Status von echo "true", verschiebe die erste Klammersetzung { an den Anfang: { (ping -c1 localhost&>/dev/null) && echo "true"; } || { echo "false"; }.

4voto

dx_over_dt Punkte 11300

Einige Leute haben bereits einige schöne Alternativen vorgestellt. Ich wollte die Syntax so nah wie möglich bringen, also schrieb ich eine Funktion namens ?.

Dies ermöglicht die Syntax:

[[ $x -eq 1 ]]; ? ./script1 : ./script2
# oder
? '[[ $x -eq 1 ]]' ./script1 : ./script2

In beiden Fällen ist das : optional. Alle Argumente, die Leerzeichen enthalten, müssen in Anführungszeichen stehen, da sie mit eval ausgeführt werden.

Wenn die oder Klauseln keine Befehle sind, gibt die Funktion den entsprechenden Wert mit echo aus.

./script; ? Erfolg! : "Fehler :("

Die Funktion

?() {
  lokale letzteRück=$?
  if [[ $1 == --help || $1 == -? ]]; then
    echo $'\e[37;1mVerwendung:\e[0m
  ? []  [:] 

Wenn \e[37;1m\e[0m und/oder \e[37;1m\e[0m keine gültigen Befehle sind, werden ihre Werte
in stdOut ausgegeben, andernfalls werden sie ausgeführt. Wenn \e[37;1m\e[0m nicht
angegeben ist, wird der Rückgabecode ($?) des vorherigen Statements ausgewertet.

\e[37;1mBeispiele:\e[0m
  myVar=$(? "[[ $x -eq 1 ]] foo bar)
  \e[32;2m# myVar wird auf "foo" gesetzt, wenn x 1 ist, ansonsten wird es auf "bar" gesetzt\e[0m

  ? "[[ $x = *foo* ]] "cat hello.txt" : "cat goodbye.txt"
  \e[32;2m# führt cat auf "hello.txt" aus, wenn x das Wort "foo" enthält, sonst führt es cat auf
  # "goodbye.txt" aus\e[0m

  ? "[[ $x -eq 1 ]] "./script1" "./script2"; ? "Erfolgreich!" "Gescheitert :("
  \e[32;2m# Wenn x = 1 ist, führt script1 aus, sonst script2. Wenn das Skript erfolgreich ausgeführt wird, wird
  # "Erfolgreich!" gedruckt, ansonsten wird "gescheitert" gedruckt.\e[0m'
    zurück
  elif ! [[ $# -eq 2 || $# -eq 3 || $# -eq 4 && $3 == ':' ]]; then
    1>&2 echo $'\e[37;1m?\e[0m benötigt 2 bis 4 Argumente

\e[37;1mVerwendung\e[0m: ? []  [:] 
Führen Sie \e[37;1m? --help\e[0m für weitere Details aus'
    zurück 1
  fi

  lokale cmd

  if [[ $# -eq 2 || $# -eq 3 && $2 == ':' ]]; then
    cmd="[[ $lastRet -eq 0 ]]"
  else
    cmd="$1"
    shift
  fi

  if [[ $2 == ':' ]]; then
    eval "set -- '$1' '$3'"
  fi

  lokale ergebnis=$(eval "$cmd" && echo "$1" || echo "$2")
  if command -v ${result[0]} &> /dev/null; then
    eval "${result[@]}"
  else
    echo "${result[@]}"
  fi
}

Natürlich können Sie den Hilfetext entfernen, wenn Sie möchten, dass das Skript kürzer wird.

EDIT: Ich war nicht darüber im Bilde, dass ? als Platzhalterzeichen in einem Dateinamen fungiert. Anstatt wie * eine beliebige Anzahl von Zeichen abzugleichen, gleicht es genau ein Zeichen ab. Wenn Sie also eine Datei mit einem einzelnen Zeichen in Ihrem Arbeitsverzeichnis haben, wird bash versuchen, den Dateinamen als Befehl auszuführen. Ich bin mir nicht sicher, wie man das umgehen kann. Ich dachte, die Verwendung von command "?" ...args könnte funktionieren, aber leider nicht.

4voto

Priyesh Patel Punkte 74

Sie können dies verwenden, wenn Sie eine ähnliche Syntax wünschen

a=$(( $((b==5)) ? c : d ))

1 Stimmen

Dies funktioniert nur mit ganzen Zahlen. Sie können es einfacher schreiben als a=$(((b==5) ? : c : d)) - $((...)) wird nur benötigt, wenn wir das Ergebnis der Berechnung einer anderen Variablen zuweisen möchten.

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