web-dev-qa-db-fra.com

Changer de casse avec fallthrough?

Je cherche la syntaxe correcte de l'instruction switch avec les cas d'erreur dans Bash (idéalement, insensible à la casse). Dans PHP je le programmerais comme suit:

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

Je veux la même chose dans Bash:

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

Cela ne fonctionne pas: la fonction do_what_you_are_supposed_to_do() doit être déclenchée lorsque $ C vaut 2 OR 3.

168
Mischka

Utilisez une barre verticale (|) pour "ou".

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

Les versions récentes de bash permettent le passage direct en utilisant ;& au lieu de ;;: elles permettent également de reprendre les vérifications de cas en utilisant ;;&.

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" | ?4)
     echo -n four 
     ;;&  # resume ( to find teen where needed )
   "14" )
     echo -n teen
  esac
  echo 
done

exemple de sortie

4 = four
14 = fourteen
24 = twenty-four
34 = thirty-four
82
Jasen
  • N'utilisez pas () derrière les noms de fonctions dans bash, à moins que vous n'aimiez les définir.
  • utilisez [23] au cas où correspondre à 2 ou 3
  • les cas de chaînes statiques doivent être entourés de '' au lieu de ""

S'il est inclus dans "", l'interpréteur essaie (inutilement) de développer les variables possibles dans la valeur avant la mise en correspondance.

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

Pour une correspondance insensible à la casse, vous pouvez utiliser des classes de caractères (comme [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

Mais abra ne frappe pas à tout moment, car le premier cas va lui correspondre.

Si nécessaire, vous pouvez omettre ;; dans le premier cas pour continuer à tester les correspondances dans les cas suivants également. (;; passe à esac)

24
Sprinterfreak

Essaye ça:

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

Si les valeurs sont entières, vous pouvez utiliser [2-3] ou [5,7,8] pour les valeurs non continues.

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

Si les valeurs sont des chaînes, vous pouvez utiliser |.

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