
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 extglob
ou 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
, ksh93
ou 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 case
nã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 in
operador 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 x
se arr[$1]
estiver definido; caso contrário, vazio.)
Responder4
grep
abordagem.
if echo $1 | grep -qE "^(cat|dog|mouse)$"; then
echo "dollar 1 is either a cat or a dog or a mouse"
fi
-q
para evitar qualquer saída para a tela (é mais rápido digitar do que>/dev/null
).-E
para 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 ($
)