Несколько логических операторов ((A || B) && C) и «синтаксическая ошибка рядом с неожиданным токеном»

NetworkManager может создавать профили WPA2 Enterprise с графическим интерфейсом пользователя. nmcli и nmtui не поддерживают это, но могут использовать существующие профили.

Подробнее о подключении к сетям WPA2_Enterprise

24
16.06.2016, 15:50
3 ответа

Используйте [[:

if [[ ( "$A" -eq "0" || "$B" -ne "0" ) && "$C" -eq "0" ]]; then ...

Если вы предпочитаете [], работает следующее:

if [ \( "$A" -eq "0" -o "$B" -ne "0" \) -a "$C" -eq "0" ]; then ...
11
27.01.2020, 19:40

Используйте оператор -o вместо вложенного ||. Вы также можете использовать -a для замены &&, если это необходимо, в других ваших операторах.

   EXPRESSION1 -a EXPRESSION2
          both EXPRESSION1 and EXPRESSION2 are true

   EXPRESSION1 -o EXPRESSION2
          either EXPRESSION1 or EXPRESSION2 is true


if [  "$A" -eq "0" -o "$B" -ne "0"  ] && [ "$C" -eq "0" ]; then echo success;fi
4
27.01.2020, 19:40

Синтаксис bash не похож на C, даже если часть его вдохновлена C. Вы не можете просто попытаться написать код на C и ожидать, что он будет работать.

Основная суть оболочки - это выполнение команд. Команда open-bracket [ - это команда, которая выполняет один тест¹. Вы даже можете записать ее как test (без последней закрывающей скобки). Операторы || и && - это операторы оболочки, они объединяют команды, а не тесты.

Поэтому, когда вы пишете

[ [ "$A" -eq "0" ] || [ "$B" -ne "0" ] ] && [ "$C" -eq "0" ]

это разбирается как

[ [ "$A" -eq "0" ] ||
[ "$B" -ne "0" ] ] &&
[ "$C" -eq "0" ]

что то же самое, что и

test [ "$A" -eq "0" ||
test "$B" -ne "0" ] &&
test "$C" -eq "0"

Заметили несбалансированные скобки? Да, это нехорошо. Ваша попытка с круглыми скобками имеет ту же проблему: ложные скобки.

Синтаксис для объединения команд в группы - это скобки. Способ разбора скобок требует, чтобы перед ними была полная команда, поэтому вам придется завершить команду внутри скобок новой строкой или точкой с запятой.

if { [ "$A" -eq "0" ] || [ "$B" -ne "0" ]; } && [ "$C" -eq "0" ]; then …

Существует альтернативный способ, который заключается в использовании двойных скобок. В отличие от одинарных скобок, двойные скобки - это специальный синтаксис оболочки. Они разграничивают условные выражения. Внутри двойных скобок можно использовать круглые скобки и такие операторы, как && и ||. Поскольку двойные скобки - это синтаксис оболочки, оболочка знает, что когда эти операторы находятся внутри скобок, они являются частью синтаксиса условного выражения, а не частью синтаксиса обычной команды оболочки.

if [[ ($A -eq 0 || $B -ne 0) && $C -eq 0 ]]; then …

Если все ваши тесты являются числовыми, есть еще один способ - разграничение арифметических выражений. Арифметические выражения выполняют целочисленные вычисления с очень похожим на C синтаксисом.

if (((A == 0 || B != 0) && C == 0)); then …

Вы можете найти мой учебник по скобкам в bash полезным.

[ можно использовать в обычном sh. [[ и (( специфичны для bash (а также ksh и zsh).

¹ Он также может объединять несколько тестов с помощью булевых операторов, но это громоздко в использовании и имеет тонкие подводные камни, поэтому я не буду это объяснять.

73
27.01.2020, 19:40

Теги

Похожие вопросы