Как bash оценит следующий код

Как bash оценит следующий код

Этот вопрос состоит из двух частей:

(a) Понимание того, что делает фрагмент кода

(б) Понимание разницы междустатус выходаистатус возвратав контексте bash.

Вот фрагмент кода, который я пытаюсь понять:

if var=-2 && (( var+=2 ))
then
    echo "True"
else
    echo "False"
fi

Запуск этого дает False. Я не могу понять, почему это происходит.

Если я правильно понимаю, вот что может произойти с этим ifсостоянием:

(a) var=-2создает статус выхода 0, поскольку назначение выполнено успешно

(b) (( var+=2 ))добавляет 2 к значению varи выражение оценивается как ноль. Таким образом, статус выхода для этого термина равен 1

(c) 0 && 1 создает существующий статус 0, который затем используется ifконструкцией

Предполагается, что конструкция ifпросто проверяет статус выхода, и когда он равен нулю, она принимаетзатемpath. В шаге (c) выше он равен нулю, но скрипт все равно беретещепуть. Правильно ли это понимать?

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

Я сомневаюсь, что var=-2назначение будет иметь какой-либо статус выхода, потому что это не программа. Но любое разъяснение разницы между ними было бы здорово.

решение1

Это:

if
  first list of commands
then
  second list of commands
else
  third list of commands
fi

Это для запуска второго списка команд, если первый список команд возвращаетистинный/успех(нулевой) статус выхода, то есть если последняя запущенная команда возвращается с нулевым статусом выхода.

В:

var=-2 && ((var += 2))

Он cmd1 && cmd2запускается cmd2только в случае cmd1успеха.

var=-2

Обычно это выполняется успешно, если только $varне был сделан доступ только для чтения, поэтому ((var += 2))будет запущена команда:

((arithmetic expression))

Возвратыуспех/истинныйпри условии, что выражение вычислено правильно (нет синтаксических ошибок) и результат выражения не равен нулю.

  • ((123)), ((1 + 1)), ((1 == 1))вернуть истину
  • ((0)), ((-2 + 2)), ((2 == -2))возвращает false.
  • ((4294967296 * 4294967296))возвращают false в большинстве оболочек из-за 64-битного целочисленного переноса

var += 2как арифметическое выражение, выполняет присваивание и разрешается в присваиваемое значение, в данном случае 0, отсюда иЛОЖЬстатус выхода.

Вы можете увидеть значение, на котором основан статус выхода, используя $((...))синтаксис арифметического расширения:

$ echo "$((1 + 1)) $((2 == 2)) $((2 == -2)) $((var = -2)) $((var += 2))"
2 1 0 -2 0

Или присвоив его переменной:

$ var=-2; ((result = (var += 2)))
$ echo "$? $result $var"
1 0 0

$?содержит статус выхода предыдущей команды. Что касается if/ then/ else/ fi, 0 означает истину, все остальное означает ложь.

Путаница здесь возникает из-за того, что для арифметических выражений все наоборот: 0означает ложь, а все остальное означает истину (например, 2 == 2is , 1тогда как 2 < 1is 0).

Чтобы не беспокоиться о разнице, просто забудьте о $?и его возможных значениях. Просто думайте в терминах булевыхистинный/ЛОЖЬ,успех/отказ.

 grep -q foo file

Возвращает true, если fooнайдено в file.

 [ "$a" = "$b" ]

Возвращает true, если $aсодержит то же самое, что и $b.

 ((6 * 3 - 12))
 ((4 == 1))

Возвращает значение true, если результатом арифметического выражения является ненулевое число.

Неважно, являются ли этиистинный/ЛОЖЬвыражаются через 0 или 1 статуса выхода этих grepкоманд [или ((...))конструкций.

решение2

(c) 0 && 1 создает существующий статус 0, который затем используется ifконструкцией

Вот в чем ошибка. 0 && 1 приводит к 1. Это не C или Java, помните. В оболочке 0 && 1 — это то, что вы получите из true && false.

$ true; echo $?
0
$ false; echo $?
1
$ true && false; echo $?
1

Кроме того, я постоянно вижу, что в различных текстах bash статус выхода и статус возврата используются как взаимозаменяемые.

Они взаимозаменяемы. Что вам нужно иметь в виду, так это то, что 0указывает на успех, а не 0указывает на неудачу. Это противоположность большинству языков программирования, где 0is false и 1is true.

решение3

Все работает так, как и ожидалось.

if var=-2 && (( var+=2 ))
then
    echo "True"
else
    echo "False"
fi

Объяснение кода:-

if var=-2 && (( var+=2 ))

var=-2 => true Значение не равно нулю, поэтому оценивается как истинное.

var+=2 => false Значение равно нулю, поэтому оценивается как ложное.

это как

if true && false

Согласно логическому расчетуправда && ложь => ложь

В таком случае вот наш окончательный код

if (false)
then
    echo "True"
else
    echo "False"
fi

Связанный контент