Классическая техника (метасимволы побега):
if [ \( "$g" -eq 1 -a "$c" = "123" \) -o \( "$g" -eq 2 -a "$c" = "456" \) ]
then echo abc
else echo efg
fi
Я заключил ссылки на $g
в двойных кавычках; Это хорошая практика, в общем. Строго говоря, скобки не нужны, потому что приоритет -a
и -o
делает его правильным даже без них.
Обратите внимание, что операторы -a
и -o
являются частью спецификации POSIX для test
, или [
, в основном для обратной совместимости (поскольку они были частью test
например, в 7-м издании UNIX), но POSIX явно помечает их как «устаревшие». Bash (см. условные выражения ), кажется, вытесняет классические значения и значения POSIX для -a
и -o
своими собственными альтернативными операторами, которые принимают аргументы.
С некоторой осторожностью вы можете использовать более современный оператор [[
, но имейте в виду, что версии в Bash и Korn Shell (например) не обязательно должны быть идентичными.
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
Пример запуска с использованием Bash 3.2.57 в 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
Вам не нужно заключать переменные в [[
в кавычки, как вы делаете с [
, потому что это не отдельная команда, как [
.
Разве это не классический вопрос?
Я бы так и подумал. Однако есть и другая альтернатива, а именно:
if [ "$g" -eq 1 -a "$c" = "123" ] || [ "$g" -eq 2 -a "$c" = "456" ]
then echo abc
else echo efg
fi
Действительно, если вы прочитали рекомендации по «портативной оболочке» для инструмента autoconf
или связанных пакетов, то эти обозначения - с использованием '||
' и '&&
' - это то, что они рекомендуют. Я полагаю, вы могли бы даже пойти так далеко:
if [ "$g" -eq 1 ] && [ "$c" = "123" ]
then echo abc
elif [ "$g" -eq 2 ] && [ "$c" = "456" ]
then echo abc
else echo efg
fi
Там, где действия столь же тривиальны, как эхо, это неплохо. Когда блок действий, который должен повторяться, состоит из нескольких строк, повторение слишком болезненное, и предпочтительна одна из более ранних версий - или вам нужно заключить действия в функцию, которая вызывается в различных блоках then
.