Bash if оператор с несколькими условиями выдает ошибку


165

Я пытаюсь написать сценарий, который будет проверять два флага ошибок, и в случае изменения одного флага (или обоих) будет эхо- ошибка произошла. Мой сценарий:

my_error_flag=0
my_error_flag_o=0
do something.....
if [[ "$my_error_flag"=="1" || "$my_error_flag_o"=="2" ] || [ "$my_error_flag"="1" &&     "$my_error_flag_o"="2" ]]; then
    echo "$my_error_flag"
else
    echo "no flag"
fi

В принципе, так и должно быть:

if ((a=1 or b=2) or (a=1 and b=2))
  then
     display error
else
     no error
fi

Я получаю ошибку:

 line 26: conditional binary operator expected
 line 26: syntax error near `]'
 line 26: `if [[ "$my_error_flag"=="1" || "$my_error_flag_o"=="2" ] || [ "$my_error_flag"="1" && "$my_error_flag_o"="2" ]]; then'

Мои кронштейны испорчены?



2
Используйте круглые скобки - ()
АликЭльзин-килака


3
По логике a==1 or b==2уже охватывает тот случай, когда a==1 and b==2. Тестирование отдельно для этого совершенно излишне.
tripleee

Ответы:


249

Используйте -a(для и) и -o(для или) операции.

tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html

Обновить

На самом деле вы все еще можете использовать &&и ||с -eqоперацией. Итак, ваш сценарий будет выглядеть так:

my_error_flag=1
my_error_flag_o=1
if [ $my_error_flag -eq 1 ] ||  [ $my_error_flag_o -eq 2 ] || ([ $my_error_flag -eq 1 ] && [ $my_error_flag_o -eq 2 ]); then
      echo "$my_error_flag"
else
    echo "no flag"
fi

Хотя в вашем случае вы можете отбросить последние два выражения и просто придерживаться одного или операции, например:

my_error_flag=1
my_error_flag_o=1
if [ $my_error_flag -eq 1 ] ||  [ $my_error_flag_o -eq 2 ]; then
      echo "$my_error_flag"
else
    echo "no flag"
fi

3
@Simply_Me: Нет, логическое ИЛИ истинно, если один или оба из его операндов верны. Вы думаете об «исключительном или» (XOR), что верно, если точно один из его операндов истинен. (На самом деле, существуют версии XOR, которые работают более чем с 2 операндами, и в этом случае это правда, если нечетное число операндов истинно.)
Гордон Дэвиссон

4
Кстати, проблемы в исходном коде включают использование [и ]для группировки (они этого не делают) и невозможность поместить пробелы вокруг оператора (например "$my_error_flag"="1"), что не позволяет оболочке вообще его распознавать как оператор. Пожалуйста, прочтите BashFAQ № 17 (о группировке) и № 31 (о разнице между различными типами тестовых выражений) . На самом деле, в этом случае было бы еще проще использовать арифметическое выражение .
Гордон Дэвиссон

7
-aи -oсчитаются устаревшими по спецификации POSIX ; использовать отдельные тесты в сочетании с ||как в обновлении.
chepner

1
Нет необходимости группировать с использованием подоболочек, обычно {}также возможно группирование с использованием .
23.09.16

1
Чтобы добавить к комментарию phk выше, () запускает подоболочки в bash, которые могут иметь все виды тонких [вероятно нежелательных] эффектов.
Бретт

70

Вы можете использовать любой [[или ((ключевое слово. При использовании [[ключевых слов, вы должны использовать строковые операторы , такие как -eq, -lt. Я думаю, ((наиболее предпочтительным для арифметики, потому что вы можете напрямую использовать операторы, такие как ==, <и >.

Использование [[оператора

a=$1
b=$2
if [[ a -eq 1 || b -eq 2 ]] || [[ a -eq 3 && b -eq 4 ]]
then
     echo "Error"
else
     echo "No Error"
fi

Использование ((оператора

a=$1
b=$2
if (( a == 1 || b == 2 )) || (( a == 3 && b == 4 ))
then
     echo "Error"
else
     echo "No Error"
fi

Не используйте -aили -oоператоры, поскольку он не является портативным.


8

Пожалуйста, попробуйте следующее

if ([ $dateR -ge 234 ] && [ $dateR -lt 238 ]) || ([ $dateR -ge 834 ] && [ $dateR -lt 838 ]) || ([ $dateR -ge 1434 ] && [ $dateR -lt 1438 ]) || ([ $dateR -ge 2034 ] && [ $dateR -lt 2038 ]) ;
then
    echo "WORKING"
else
    echo "Out of range!"

2
( ... )создает подоболочки - большое влияние на производительность без пользы.
Чарльз Даффи

4
Используйте { ...; }для группировки без создания подоболочки.
Чарльз Даффи

1

Вы можете получить вдохновение, прочитав entrypoint.sh сценарий написанный участниками MySQL, который проверяет, установлены ли указанные переменные.

Как показывает сценарий, вы можете передать их -a, например:

if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
    ...
fi

1
-aпомечен как устаревший в текущей версии testстандарта POSIX ; см. OBмаркеры на pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html . Используйте, [ -z "$FOO" ] && [ -z "$BAR" ]чтобы иметь более надежный код.
Чарльз Даффи
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.