Класична техніка (метахарактеристика втечі):
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
блоках.
test
([
), а не оболонкою. Оболонка оцінює лише статус виходу[
.