Как представить несколько условий в операторе shell if?
Я хочу представить несколько условий такой:
if [ ( $g -eq 1 -a "$c" = "123" ) -o ( $g -eq 2 -a "$c" = "456" ) ]
then
echo abc;
else
echo efg;
fi
но когда я выполняю скрипт, он показывает
syntax error at line 15: `[' unexpected,
где строка 15 показывает, если ....
что не так с этим условием? Я думаю, что-то не так с ()
.
6 ответов
классическая техника (побег метасимволы):
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. Баш (см. условные выражения), кажется, превзойти классические и POSIX значения для -a
и -o
со своими альтернативными операторами, которые принимают аргументы.
С некоторой осторожностью вы можете использовать более современный [[
оператор, но имейте в виду, что версии в оболочке Bash и Korn (например) не должны быть идентичный.
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
действительно, если Вы читаете " портативный руководство shell для autoconf
инструмент или связанные пакеты, это обозначение-с помощью'||
' и '&&
' - это то, что они рекомендуют. Я полагаю, вы могли бы даже зайти так далеко:
if [ "$g" -eq 1 ] && [ "$c" = "123" ]
then echo abc
elif [ "$g" -eq 2 ] && [ "$c" = "456" ]
then echo abc
else echo efg
fi
где действия столь же тривиальны, как эхо, это неплохо. Когда блок действий, который нужно повторить, состоит из нескольких строк, повторение слишком болезненно, и одна из более ранних версий предпочтительнее - или вам нужно обернуть действия в функцию, которая вызывается в другом then
блоки.
используя /bin/bash
следующие работы:
if [ "$option" = "Y" ] || [ "$option" = "y" ]; then
echo "Entered $option"
fi
$ g=3
$ c=133
$ ([ "$g$c" = "1123" ] || [ "$g$c" = "2456" ]) && echo "abc" || echo "efg"
efg
$ g=1
$ c=123
$ ([ "$g$c" = "1123" ] || [ "$g$c" = "2456" ]) && echo "abc" || echo "efg"
abc
будьте осторожны, если у вас есть пробелы в строковых переменных и проверить наличие. Обязательно цитируйте их правильно.
if [ ! "${somepath}" ] || [ ! "${otherstring}" ] || [ ! "${barstring}" ] ; then
#!/bin/bash
current_usage=$( df -h | grep 'gfsvg-gfslv' | awk {'print '} )
echo $current_usage
critical_usage=6%
warning_usage=3%
if [[ ${current_usage%?} -lt ${warning_usage%?} ]]; then
echo OK current usage is $current_usage
elif [[ ${current_usage%?} -ge ${warning_usage%?} ]] && [[ ${current_usage%?} -lt ${critical_usage%?} ]]; then
echo Warning $current_usage
else
echo Critical $current_usage
fi