Когда вы пишете:
var=$(cmd)
, вывод cmd
присваивается var
(без разделения слов), а $?
устанавливается на значение, возвращаемое cmd
.
Когда вы пишете:
var=$(cmd1) cmd2
cmd1
выполняется и его вывод (без разделения слов) присваивается переменной var
в среде cmd2
, котораязатем выполнен. $?
устанавливается на значение, возвращаемое cmd2
.
Когда вы пишете:
cmd1 var=$(cmd2)
cmd2
, строка var=output of cmd2
подвергается разбиению по словам и передается как аргумент (ы) cmd1
, а $?
устанавливается на значение, возвращаемое cmd1
. (Почти во всех случаях вы хотите подавить разделение слов и вместо этого написать cmd1 var="$(cmd2)"
, что гарантирует передачу только одного аргумента.)
local
- это команда, а local myfunc_out=$(myfunc $1)
- это3-я форма (с предупреждением), поэтому она устанавливает $?
на значение, возвращаемое local
. Обратите внимание, что если выходные данные myfunc $1
содержат пробелы, разделение слов происходит , а не . Процитируем man-страницу: Assignment statements may also appear as arguments to the alias, declare, typeset, export, readonly, and local builtin commands
, так что строка считается присвоением переменной, а разделение слов не выполняется.
Короче говоря, local
имеет выходное значение и используется для установки $?
Вместо назначения присваивания аргумента для local
, вы можете использовать:
local myfunc_out myfunc_rc
myfunc_out="$(myfunc $1)"; myfunc_rc=$?
Обратите внимание, что двойные кавычки здесь не являются строго необходимыми, поскольку разделение слов не происходитв задании, но их использование, безусловно, является хорошей практикой.