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 $gentre aspas duplas; Essa é uma boa prática, em geral. Estritamente, os parênteses não são necessários porque a precedência -ae -oa corrige mesmo sem eles.
Note que o -ae -ooperadores são parte da especificação POSIX para test, aka [, principalmente para compatibilidade com versões anteriores (desde que eles eram uma parte testna 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 -ae -ocom 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 autoconfferramenta 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 thenblocos.
test([) e não pelo shell. O shell avalia apenas o status de saída de[.