Ответ 1
Классическая техника (метасимволы выхода):
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
, aka [
, в основном для обратной совместимости (поскольку они были частью 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
.