Técnica clássica (metacaracteres de escape):
if [ \( "$g" -eq 1 -a "$c" = "123" \) -o \( "$g" -eq 2 -a "$c" = "456" \) ]
then echo abc
else echo efg
fi
Coloquei as referências $g
entre aspas duplas; Essa é uma boa prática, em geral. Estritamente, os parênteses não são necessários porque a precedência -a
e -o
a corrige mesmo sem eles.
Note que o -a
e -o
operadores são parte da especificação POSIX para test
, aka [
, principalmente para compatibilidade com versões anteriores (desde que eles eram uma parte test
na 7ª Edição UNIX, por exemplo), mas eles são explicitamente marcados como 'obsoletos' por POSIX. O Bash (consulte expressões condicionais ) parece antecipar os significados clássico e POSIX para -a
e -o
com seus próprios operadores alternativos que recebem argumentos.
Com algum cuidado, você pode usar o [[
operador mais moderno , mas lembre-se de que as versões no Bash e Korn Shell (por exemplo) não precisam ser idênticas.
for g in 1 2 3
do
for c in 123 456 789
do
if [[ ( "$g" -eq 1 && "$c" = "123" ) || ( "$g" -eq 2 && "$c" = "456" ) ]]
then echo "g = $g; c = $c; true"
else echo "g = $g; c = $c; false"
fi
done
done
Exemplo de execução, usando o Bash 3.2.57 no Mac OS X:
g = 1; c = 123; true
g = 1; c = 456; false
g = 1; c = 789; false
g = 2; c = 123; false
g = 2; c = 456; true
g = 2; c = 789; false
g = 3; c = 123; false
g = 3; c = 456; false
g = 3; c = 789; false
Você não precisa citar as variáveis [[
como faz [
porque não é um comando separado da mesma maneira que [
é.
Não é uma pergunta clássica?
Eu teria pensado assim. No entanto, existe outra alternativa, a saber:
if [ "$g" -eq 1 -a "$c" = "123" ] || [ "$g" -eq 2 -a "$c" = "456" ]
then echo abc
else echo efg
fi
De fato, se você ler as diretrizes do 'shell portátil' para a autoconf
ferramenta ou pacotes relacionados, essa notação - usando ' ||
' e ' &&
' - é o que eles recomendam. Suponho que você poderia ir tão longe quanto:
if [ "$g" -eq 1 ] && [ "$c" = "123" ]
then echo abc
elif [ "$g" -eq 2 ] && [ "$c" = "456" ]
then echo abc
else echo efg
fi
Onde as ações são tão triviais quanto ecoantes, isso não é ruim. Quando o bloco de ação a ser repetido possui várias linhas, a repetição é muito dolorosa e uma das versões anteriores é preferível - ou você precisa agrupar as ações em uma função que é invocada nos diferentes then
blocos.
test
([
) e não pelo shell. O shell avalia apenas o status de saída de[
.