ローカルfn = $(...)が$をマスクするのはなぜですか?ステータスコード

ローカルfn = $(...)が$をマスクするのはなぜですか?ステータスコード

2つの関数定義の唯一の違いは、1つ目はlocal保存キーワードを割り当てと組み合わせ、2つ目はそれを分離することです。

function foo {
    local fn=$(mktemp -p /path/does/not/exist 2>/dev/null)
    echo $?
}

function bar {
    local fn
    fn=$(mktemp -p /path/does/not/exist 2>/dev/null)
    echo $?
}

foo
bar

最初は「0」、次に「1」です。まず「1」をエコーし​​、次に「1」をエコーし​​たい。値は、$?コマンド置換の結果ではなく、ローカルに割り当てた結果のようです。

bash 4.2.46(1) - リリースはなぜこのように動作しますか?

答え1

私はこの動作が問題なので明示的に文書化されたと思いましたが(特に-o errexit!でbashスクリプトを実行するとき)、そうではありません。私のマニュアルのコピーには次のように指定されています(about、global関数の内部と同じように動作します)。local

無効なオプションが見つからない限り、 '-f foo=bar' を使用して関数を定義し、読み取り専用変数に値を割り当ててみて、複合割り当て構文を使わずに配列変数に値を割り当ててみてください。 [...] 、名前の1つが有効なシェル変数名ではありません。読み取り専用変数の読み取り専用状態をオフにしたり、配列変数の配列状態をオフにしたり、-fを使用して存在しない関数を表示したりします。それ以外の場合、戻り状態は0です。

したがって、これは他のプログラミング言語で予想されるキーワードとは見えませんlocal。割り当てに似たパラメータが引数に指定されている場合は、local代わりに初期化を制限しません。local 組み込みコマンド割り当ての発生を担当し、戻りコードはlocal 初期化プログラムで実行できるコードではなく、それ自体であり、その戻りコードは上記の条件リストでのみゼロではありません。

Bishopがコメントで述べたように、もう少し文字通り質問に答えるために、bash管理者であるChet Rameyは、local割り当て中に反射が失敗することを考慮するかどうかを尋ねられ、基本的に次のように答えました。local課題は主な仕事ではありません。 :

なぜなら、それは地域社会とその兄弟姉妹が[…]することではないからです。これらの組み込み関数は、変数属性を割り当てて変更するために存在します。アドオンとして割り当てもサポートする上で重要な機能はプロパティ設定です。値がどのように計算されるかを知る必要はありません。 [...]関数はプロパティまたは値を設定するため、終了ステータスは操作が成功したかどうかを反映する必要があります。

zsh同じ動作がシェルでも観察できることは注目に値します。

解決策は、次の2つのタスクを分離することです。

local variable
variable=$( somecommand )

exit_status=$?

関連情報