
Этот вопрос состоит из двух частей:
(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 == 2
is , 1
тогда как 2 < 1
is 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
указывает на неудачу. Это противоположность большинству языков программирования, где 0
is false и 1
is 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