Смотрите следующие примеры и их вывод в оболочках POSIX:
false;echo $?
илиfalse || echo 1
:1
false;foo="bar";echo $?
илиfoo="bar" && echo 0
:0
foo=$(false);echo $?
илиfoo=$(false) || echo 1
:1
foo=$(true);echo $?
илиfoo=$(true) && echo 0
:0
Как указано в ответе с наибольшим количеством голосов на /programming/6834487/what-is-the-variable-in-shell-scripting :
$?
используется для поиска возвращаемого значения последней выполненной команды.
Это, вероятно, немного вводит в заблуждение в этом случае, поэтому давайте получим определение POSIX, которое также приводится в сообщении из этой темы:
? Расширяется до десятичного состояния выхода самого последнего конвейера (см. Конвейеры).
Таким образом, создается впечатление, что само назначение считается как команда (или, скорее, часть конвейера) с нулевым значением выхода, но которая применяется перед правой стороной назначения (например, вызовы подстановки команд в моих примерах здесь).
Я вижу, как это поведение имеет смысл с практической точки зрения, но мне кажется несколько необычным, что само назначение будет учитываться в этом порядке. Может быть, чтобы прояснить, почему это странно для меня, давайте предположим, что назначение было функцией:
ASSIGNMENT( VARIABLE, VALUE )
тогда foo="bar"
будет
ASSIGNMENT( "foo", "bar" )
и foo=$(false)
было бы что-то вроде
ASSIGNMENT( "foo", EXECUTE( "false" ) )
Это означает, что EXECUTE
запускается сначала, а только потом ASSIGNMENT
запускается, но здесь все равно имеет значение EXECUTE
статус.
Правильно ли я оцениваю или я что-то недопонимаю? Это правильные причины, по которым я считаю это поведение "странным"?
false;foo="bar";echo $?
всегда возвращается 0, когда была последняя действительная командаfalse
?» Это в основном то, что назначения ведут себя особенным, когда дело доходит до кодов выхода. Их код выхода всегда равен 0, за исключением случаев, когда это происходит не из-за чего-то, что выполнялось как часть правой части назначения.Ответы:
Статус выхода для назначений странный . Наиболее очевидный способ провала назначения - если помечена целевая переменная
readonly
.Обратите внимание, что ни истинные, ни ложные пути оператора if не были приняты, при неудачном назначении выполнение всего оператора не прекращалось. bash в режиме POSIX, а ksh93 и zsh прервут выполнение сценария, если назначение не выполнено.
Чтобы процитировать стандарт POSIX на этом :
Это именно та часть грамматики оболочки, которая используется в
который приходит из
simple_command
(simple_command → cmd_prefix → ASSIGNMENT_WORD). Таким образом, если присвоение завершается успешно, то статус выхода равен нулю, если не была задействована подстановка команд, и в этом случае статусом выхода является статус последнего. Если назначение не выполнено, то состояние выхода не равно нулю, но вы не сможете его поймать.источник
Ты говоришь,
Это не ужасный взгляд на это. Но это небольшое упрощение. Общий статус возврата от
это статус выхода из . Задание , которое происходит после того , как задание не устанавливает статус выхода в целом 0.cmd4
E=
D=
Также, как указывает Икар , переменные могут быть установлены только для чтения. Рассмотрим следующий вариант на примере Икара:
Несмотря на то, что
A
он доступен только для чтения, bash выполняет подстановку команд справа отA=
- и затем прерывает команду, потому что только дляA
чтения. Это также противоречит вашей интерпретации того, что выходное значение присвоения применяется перед правой стороной присвоения.источник