Переключить случай с падением? - PullRequest
167 голосов
/ 06 апреля 2011

Я ищу правильный синтаксис оператора switch с падениями в Bash (в идеале без учета регистра). В PHP я бы запрограммировал это так:

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

Я хочу то же самое в Bash:

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

Это почему-то не работает: функция do_what_you_are_supposed_to_do() должна запускаться, когда $ C равен 2 ИЛИ 3.

Ответы [ 5 ]

274 голосов
/ 06 апреля 2011

Используйте вертикальную черту (|) для "или".

case "$C" in
"1")
    do_this()
    ;;
"2" | "3")
    do_what_you_are_supposed_to_do()
    ;;
*)
    do_nothing()
    ;;
esac
79 голосов
/ 03 июля 2014

В последних bash версиях разрешено использовать ;& вместо ;;: они также позволяют возобновить проверки с использованием ;;& там.

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

образец вывода

4 = four
14 = fourteen
24 = twenty-four
34 = thirty-four
24 голосов
/ 22 марта 2014
  • Не используйте () за именами функций в bash, если вы не хотите их определять.
  • используйте [23] в случае совпадения 2 или 3
  • случаи статических строк должны быть заключены в '' вместо ""

Если заключено в "", интерпретатор (без необходимости) пытается расширить возможные переменные в значении перед сопоставлением.

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

Для сопоставления без учета регистра вы можете использовать классы символов (например, [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

Но abra ни разу не попал, потому что это будет соответствовать первому случаю.

При необходимости вы можете опустить ;; в первом случае, чтобы продолжить тестирование на совпадения и в следующих случаях. (;; переходит на esac)

11 голосов
/ 21 августа 2015

Попробуйте это:

case $VAR in
normal)
    echo "This doesn't do fallthrough"
    ;;
special)
    echo -n "This does "
    ;&
fallthrough)
    echo "fall-through"
    ;;
esac
10 голосов
/ 03 апреля 2018

Если значения целые, то вы можете использовать [2-3] или [5,7,8] для непостоянных значений.

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

Если значения строковые, вы можете использовать |.

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