Gehäuse mit Durchfall wechseln?


193

Ich suche nach der richtigen Syntax der switch-Anweisung mit Fallthrough-Fällen in Bash (idealerweise ohne Berücksichtigung der Groß- und Kleinschreibung). In PHP würde ich es wie folgt programmieren:

switch($c) {
    case 1:
        do_this();
        break;
     case 2:
     case 3:
        do_what_you_are_supposed_to_do();
        break;
     default:
        do_nothing(); 
}

Ich möchte dasselbe in Bash:

case "$C" in
    "1")
        do_this()
        ;;
    "2")
    "3")
        do_what_you_are_supposed_to_do()
        ;;
    *)
        do_nothing();
        ;; 
esac

Das funktioniert irgendwie nicht: Die Funktion do_what_you_are_supposed_to_do()sollte ausgelöst werden, wenn $ C 2 ODER 3 ist.


4
Verwenden Sie keine Anruffunktionen mit Parens !!! Da Sie eine Funktion in Bash definieren können, indem Sie entweder einen function fname { echo "Inside fname"; return 0; }oder einen fname() { echo "inside fname"; return 0; }Parens für einen Funktionsaufruf verwenden, kann dies so aussehen, als wäre es eine Funktionsdefinition. Funktionen sind wie alle anderen Kommandozeilen - Programm wie genannt werden mv, cp, rsync, ls, cd, etc ... In diesem Fall sind wir fname gerne so nennen: fname $ARGS.
— Charles Addis

do_nothing()soll eine SKIP-Erklärung sein? Verwenden Sie :.
— Sjas

Antworten:


309

Verwenden Sie einen vertikalen Balken ( |) für "oder".

case "$C" in
"1")
    do_this()
    ;;
"2" | "3")
    do_what_you_are_supposed_to_do()
    ;;
*)
    do_nothing()
    ;;
esac

30
Oder in diesem einfachen Fall eine Charakterklasse[23])
— SiegeX

4
@Mischka - Ich stelle fest, dass Sie diese Antwort nicht akzeptiert haben. Ist das so, weil sie den Fallthrough-Teil der Frage nicht beantwortet? Fallthrough-Logik ist nützlich, wenn zuvor eine spezielle Verarbeitung erfolgen sollte. Wenn Sie do_what_you_are_supposed_to_do()sowohl "2" als auch "3" in einem einzigen Fall zusammenfassen, wird dies nicht behoben . Ich bin mir nicht sicher, ob es sinnvoll ist, die Frage zu bearbeiten, um dies klarer zu machen, da es offensichtlich ist, dass viele Leute diese Antwort hilfreich fanden.
— Tyson

1
@Tyson Das OP hat die Antwort nicht akzeptiert, da es sich um einen nicht registrierten Benutzer handelt. In Bezug auf die "Durchfall" -Logik, wie sie normalerweise von Programmierern verstanden wird, zeigt der Fragetext einen Zusammenbruch des Zustands, nicht eine Durchfalllogik . (Beachten Sie die Verwendung von breakin der PHP - Code.) Bearbeiten der Frage, oder der Titel, zu diesem Zeitpunkt viele Antworten ungültig machen würde , die keine Durchfall Logik zur Verfügung stellen, und wahrscheinlich nicht getan werden sollte. Fall-through war erst nach mehreren Änderungen durch andere Benutzer im Titel enthalten, aber es ist zu spät, um es jetzt wieder herauszunehmen.
— user7412956

100

Neuere bashVersionen ermöglichen das Durchfallen durch Verwendung ;&von anstelle von ;;: Sie ermöglichen auch die Wiederaufnahme der Fallprüfungen, indem sie ;;&dort verwendet werden.

for n in 4 14 24 34
do
  echo -n "$n = "
  case "$n" in
   3? )
     echo -n thirty-
     ;;&   #resume (to find ?4 later )
   "24" )
     echo -n twenty-
     ;&   #fallthru
   "4" | [13]4)
     echo -n four 
     ;;&  # resume ( to find teen where needed )
   "14" )
     echo -n teen
  esac
  echo 
done

Beispielausgabe

4 = four
14 = fourteen
24 = twenty-four
34 = thirty-four

1
Diese Logik in diesem Beispiel war schwer zu befolgen. Ich glaube auch nicht, dass dieses Beispiel den Unterschied zwischen ;&und wirklich zeigt ;;&. Ich änderte die "24"an ;;& # resumeund bekam die gleichen Ergebnisse, so frage ich mich immer noch , wenn Sie verwenden würden ;&fallthrough.
— wisbucky

1
Es ist ein einfaches Beispiel für eine komplexe Sache - ich habe mich geändert ?4, [13]4um es offensichtlicher zu machen und um Ihre Änderung zu einer bahnbrechenden Änderung zu machen
— Jasen

26
  • Verwenden ()Sie in bash keine Funktionsnamen hinter, es sei denn, Sie möchten sie definieren.
  • Verwenden Sie [23]für den Fall, dass 2oder3
  • statische Zeichenfolgen sollten von ''statt eingeschlossen werden""

Wenn eingeschlossen "", versucht der Interpreter (unnötig), mögliche Variablen im Wert vor dem Abgleich zu erweitern.

case "$C" in
'1')
    do_this
    ;;
[23])
    do_what_you_are_supposed_to_do
    ;;
*)
    do_nothing
    ;;
esac

Für Übereinstimmungen ohne Berücksichtigung der Groß- und Kleinschreibung können Sie Zeichenklassen (wie [23]) verwenden:

case "$C" in

# will match C='Abra' and C='abra'
[Aa]'bra')
    do_mysterious_things
    ;;

# will match all letter cases at any char like `abra`, `ABRA` or `AbRa`
[Aa][Bb][Rr][Aa])
    do_wild_mysterious_things
    ;;

esac

Hat abraaber zu keinem Zeitpunkt getroffen, da es vom ersten Fall abgeglichen wird.

Bei Bedarf können Sie ;;im ersten Fall weglassen, um auch in den folgenden Fällen nach Übereinstimmungen zu suchen. ( ;;springt zu esac)


Sie können C auch in Kleinbuchstaben umwandeln, case "${C,,}" inwenn die Groß- / Kleinschreibung nicht wichtig ist
— Sprinterfreak

1
Was passiert, wenn Sie das weglassen ;;? ;&Solltest du nicht zum Durchfallen verwenden?
— HelloGoodbye

1
Ich erhalte einen Syntaxfehler, wenn ich weglasse, dass ;; ich ihn verwenden muss, ;;&wenn ich weiter testen möchte.
— Jasen

do_wild_mysterious_thingsmachte meinen Tag
— Julien__

14

Versuche dies:

case $VAR in
normal)
    echo "This doesn't do fallthrough"
    ;;
special)
    echo -n "This does "
    ;&
fallthrough)
    echo "fall-through"
    ;;
esac

1
Das ist ein sehr hilfreicher Tipp. Zumindest für Bash 4.3.11. Ich habe mich nicht darum gekümmert, es an anderen zu versuchen.
— Daniel

3
Hinweis: Dies funktioniert nicht für Bash 3.2, das in macOS immer noch das Standard-Bash ist.
— Danny Kirchmeier

13

Wenn die Werte ganzzahlig sind, können Sie sie verwenden [2-3]oder [5,7,8]für nicht kontinuierliche Werte verwenden.

#!/bin/bash
while [ $# -gt 0 ];
do
    case $1 in
    1)
        echo "one"
        ;;
    [2-3])
        echo "two or three"
        ;;
    [4-6])
        echo "four to six"
        ;;
    [7,9])
        echo "seven or nine"
        ;;
    *)
        echo "others"
        ;;
    esac
    shift
done

Wenn die Werte Zeichenfolge sind, können Sie verwenden |.

#!/bin/bash
while [ $# -gt 0 ];
do
    case $1 in
    "one")
        echo "one"
        ;;
    "two" | "three")
        echo "two or three"
        ;;
    *)
        echo "others"
        ;;
    esac
    shift
done

Wofür ist das shiftam Ende?
— Milkncookiez

1
shiftEntfernt das erste Argument in der Liste der CLI-Argumente. Grundsätzlich wird bei jeder Iteration dieser Schleife immer $1verwendet, um jedes Argument mit Hilfe von aus der CLI-Argumentliste abzurufen shift.
— Rashok
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.