Классическая техника (метасимволы экранирования):
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 (см. Условные выражения ), кажется, вытесняет классические значения -a
и значения POSIX для -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
блоках.
test
([
), а не оболочкой. Оболочка оценивает только состояние выхода[
.