Есть ли оператор «in» в bash/bourne?

Есть ли оператор «in» в bash/bourne?

Я ищу оператор «in», который работает примерно так:

if [ "$1" in ("cat","dog","mouse") ]; then
    echo "dollar 1 is either a cat or a dog or a mouse"
fi

Очевидно, что это гораздо более короткое утверждение по сравнению, скажем, с использованием нескольких проверок «или».

решение1

Вы можете использовать case...esac

$ cat in.sh 
#!/bin/bash

case "$1" in 
  "cat"|"dog"|"mouse")
    echo "dollar 1 is either a cat or a dog or a mouse"
  ;;
  *)
    echo "none of the above"
  ;;
esac

Бывший.

$ ./in.sh dog
dollar 1 is either a cat or a dog or a mouse
$ ./in.sh hamster
none of the above

С помощью ksh, bash -O extglobили zsh -o kshglobвы также можете использовать расширенный шаблон глобуса:

if [[ "$1" = @(cat|dog|mouse) ]]; then
  echo "dollar 1 is either a cat or a dog or a mouse"
else
  echo "none of the above"
fi

С помощью bash, ksh93или zshвы также можете использовать сравнение регулярных выражений:

if [[ "$1" =~ ^(cat|dog|mouse)$ ]]; then
  echo "dollar 1 is either a cat or a dog or a mouse"
else
  echo "none of the above"
fi

решение2

В bash нет проверки «in», но есть проверка regex (в bourne ее нет):

if [[ $1 =~ ^(cat|dog|mouse)$ ]]; then
    echo "dollar 1 is either a cat or a dog or a mouse"
fi

И обычно записывается с использованием переменной (меньше проблем с кавычками):

regex='^(cat|dog|mouse)$'

if [[ $1 =~ $regex ]]; then
    echo "dollar 1 is either a cat or a dog or a mouse"
fi

Для более старой оболочки Bourne необходимо использовать соответствие регистру:

case $1 in
    cat|dog|mouse)   echo "dollar 1 is either a cat or a dog or a mouse";;
esac

решение3

Использование a caseпрекрасно и хорошо, если у вас есть фиксированный набор питомцев, с которыми вы хотите сопоставить. Но это не сработает, если вам нужно построить шаблон во время выполнения, так как caseне интерпретирует чередование из расширенных параметров.

Это будет соответствовать только буквальной строке cat|dog|mouse:

patt='cat|dog|mouse'
case $1 in 
        $patt) echo "$1 matches the case" ;; 
esac

Однако вы можете использовать переменную с регулярным выражением. Пока переменная не заключена в кавычки, любые операторы регулярных выражений внутри нее имеют свои особые значения.

patt='cat|dog|mouse'
if [[ "$1" =~ ^($patt)$ ]]; then
        echo "$1 matches the pattern"
fi

Вы также можете использовать ассоциативные массивы. Проверка наличия ключа в одном из них — это самое близкое к inоператору, которое предоставляет Bash. Хотя синтаксис немного уродлив:

declare -A arr
arr[cat]=1
arr[dog]=1
arr[mouse]=1

if [ "${arr[$1]+x}" ]; then
        echo "$1 is in the array"
fi

(${arr[$1]+x}расширяется до x, если arr[$1]установлено, в противном случае остается пустым.)

решение4

grepподход.

if echo $1 | grep -qE "^(cat|dog|mouse)$"; then 
    echo "dollar 1 is either a cat or a dog or a mouse"
fi
  • -qчтобы избежать вывода на экран (быстрее вводить, чем >/dev/null).
  • -Eдля расширенных аспектов регулярных выражений (cat|dog|mouse)это необходимо.
  • ^(cat|dog|mouse)$соответствует любым строкам, начинающимся ( ^) с кошки, собаки или мыши ( (cat|dog|mouse)), за которыми следует конец строки ( $)

Связанный контент