Bash, якщо заява з кількома умовами видає помилку


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'

Мої дужки зіпсовані?


Перевірте це: theunixshell.blogspot.com/2013/05/…
Vijay

2
Використовуйте дужки - ()
AlikElzin-kilaka


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 ; використовувати окремі тести в поєднанні з, ||як і в оновленнях.
чепнер

1
Немає необхідності групувати за допомогою підшаровок, звичайно групове використання {}також повинно бути можливим.
phk

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.