Cambia custodia con fallthrough?


193

Sto cercando la sintassi corretta dell'istruzione switch con casi fallthrough in Bash (idealmente senza distinzione tra maiuscole e minuscole). In PHP lo programmerei come:

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

Voglio lo stesso in Bash:

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

Questo in qualche modo non funziona: la funzione do_what_you_are_supposed_to_do()dovrebbe essere attivata quando $ C è 2 O 3.


4
Non usare le funzioni di chiamata con i genitori !!! Dal momento che è possibile definire una funzione in bash usando uno function fname { echo "Inside fname"; return 0; }o fname() { echo "inside fname"; return 0; }ponendo parentesi su una chiamata di funzione può sembrare che sia una definizione di funzione. Le funzioni dovrebbero essere chiamati come qualsiasi altro programma a riga di comando, come mv, cp, rsync, ls, cd, ecc ... In questo caso chiamiamo fname in questo modo: fname $ARGS.
Charles Addis,

do_nothing()deve essere una dichiarazione SKIP? Usa :.
sabato

Risposte:


309

Utilizzare una barra verticale ( |) per "o".

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

31
O in questo semplice caso una classe di personaggi[23])
SiegeX

4
@Mischka - Prendo atto che non hai accettato questa risposta, è perché non risponde alla parte negativa della domanda? La logica di fallthrough è utile laddove si debba eseguire un'elaborazione speciale prima do_what_you_are_supposed_to_do(), il collasso di "2" e "3" in un singolo caso non riesce a risolvere questo problema. Non sono sicuro che modificare la domanda per renderlo più chiaro sia ragionevole, poiché è ovvio che molte persone hanno trovato utile questa risposta.
Tyson,

1
@Tyson L'OP non ha accettato la risposta, poiché è un utente non registrato. Per quanto riguarda la logica "fall-through", come normalmente intesa dai programmatori, il corpo della domanda dimostra un collasso della condizione, non una logica fall-through. (Si noti l'uso di breaknel codice php.) Modifica della domanda, o il suo titolo, a tale data sarebbe invalidare molte delle risposte che non forniscono autunno-attraverso la logica, e probabilmente non dovrebbe essere fatto. Fall-through non era nel titolo fino a diverse modifiche da parte di altri utenti, ma è troppo tardi per ritirarlo ora.
user7412956

100

Le bashversioni recenti consentono il fall-through usando ;&al posto di ;;: consentono anche di riprendere i controlli del caso usando ;;&lì.

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

uscita campione

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

1
Questa logica in questo esempio era difficile da seguire. Inoltre, non credo che questo esempio dimostri davvero la differenza tra ;&e ;;&. Ho cambiato la "24"a ;;& # resumeed ho ottenuto gli stessi risultati, quindi mi sto ancora chiedendo quando si usa ;&falltrough.
Wisbucky

1
è un semplice esempio di una cosa complessa - ho cambiato ?4per [13]4renderlo più ovvio e per rendere il tuo cambiamento un cambiamento
decisivo

26
  • Non usare ()dietro nomi di funzioni in bash a meno che non ti piaccia definirli.
  • utilizzare [23]nel caso di abbinare 2o3
  • i casi di stringhe statiche devono essere racchiusi in ''invece di""

Se racchiuso in "", l'interprete (inutilmente) tenta di espandere possibili variabili nel valore prima della corrispondenza.

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

Per la corrispondenza senza distinzione tra maiuscole e minuscole, puoi utilizzare le classi di caratteri (come [23]):

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

Ma abranon ha colpito in qualsiasi momento perché sarà abbinato al primo caso.

Se necessario, puoi omettere ;;nel primo caso di continuare a testare le partite anche nei seguenti casi. ( ;;passa a esac)


Puoi anche convertire C in minuscolo case "${C,,}" inse il caso non è importante
Sprinterfreak il

1
Cosa succede se si omette il ;;? Non dovresti usare ;&per fallthrough?
Ciao addio,

1
Ottengo un errore di sintassi se ometto che ;; devo usare ;;&se voglio continuare il test.
Jasen,

do_wild_mysterious_thingsreso il mio giorno
Julien__

14

Prova questo:

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

1
questo è un consiglio molto utile. Almeno per Bash 4.3.11. Non mi sono preoccupato di provarlo su nessun altro.
Daniel,

3
Nota: questo non funziona con bash 3.2, che è ancora il bash predefinito in macOS.
Danny Kirchmeier,

13

Se i valori sono interi, è possibile utilizzare [2-3]o è possibile utilizzare [5,7,8]per valori non continui.

#!/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

Se i valori sono stringa, è possibile utilizzare |.

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

a cosa serve shiftla fine?
Milkncookiez,

1
shiftrimuove il primo argomento dall'elenco degli argomenti della CLI. Fondamentalmente su ogni iterazione di questo ciclo $1viene sempre usato per ottenere ogni argomento dalla lista degli argomenti della CLI con l'aiuto di shift.
rashok,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.