Existe um operador "in" no bash/bourne?

Existe um operador "in" no bash/bourne?

Estou procurando um operador “in” que funcione mais ou menos assim:

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

Obviamente, é uma afirmação muito mais curta em comparação com, digamos, o uso de vários testes "ou".

Responder1

Você pode usar 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

Ex.

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

Com ksh, bash -O extglobou zsh -o kshglob, você também pode usar um padrão glob estendido:

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

Com bash, ksh93ou zsh, você também pode usar uma comparação de expressões regulares:

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

Responder2

Não existe um teste "in" no bash, mas existe um teste regex (não no bourne):

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

E geralmente escrito usando uma variável (menos problemas com citações):

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

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

Para um shell Bourne mais antigo, você precisa usar uma correspondência de caso:

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

Responder3

Usar um caseé bom se você tiver um conjunto fixo de animais de estimação com os quais deseja combinar. Mas não funcionará se você precisar construir o padrão em tempo de execução, pois casenão interpreta a alternância dentro dos parâmetros expandidos.

Isso corresponderá apenas à string literal cat|dog|mouse:

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

Você pode, no entanto, usar uma variável com correspondência de expressão regular. Contanto que a variável não esteja entre aspas, quaisquer operadores regex dentro dela terão seus significados especiais.

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

Você também pode usar matrizes associativas. Verificar se existe uma chave em um deles é a coisa mais próxima de um inoperador que o Bash fornece. Embora a sintaxe seja um pouco feia:

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}expande para xse arr[$1]estiver definido; caso contrário, vazio.)

Responder4

grepabordagem.

if echo $1 | grep -qE "^(cat|dog|mouse)$"; then 
    echo "dollar 1 is either a cat or a dog or a mouse"
fi
  • -qpara evitar qualquer saída para a tela (é mais rápido digitar do que >/dev/null).
  • -Epara aspectos de expressões regulares estendidas (cat|dog|mouse)precisa disso.
  • ^(cat|dog|mouse)$corresponde a qualquer linha que comece ( ^) com gato, cachorro ou mouse ( (cat|dog|mouse)) seguido pelo final da linha ( $)

informação relacionada