Смотрите следующие примеры и их вывод в оболочках 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, за исключением случаев, когда это происходит не из-за чего-то, что выполнялось как часть правой части назначения.