Смотрите следующие примеры и их вывод в оболочках POSIX:
false;echo $?илиfalse || echo 1:1false;foo="bar";echo $?илиfoo="bar" && echo 0:0foo=$(false);echo $?илиfoo=$(false) || echo 1:1foo=$(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, за исключением случаев, когда это происходит не из-за чего-то, что выполнялось как часть правой части назначения.