現在のBashではLAB_MODE=devである。
現在値を変えず、次の子BashだけでLAB_MODE=prodと表示する。
適切なコマンドはどれか。
単純コマンドの直前に置く変数代入は、そのコマンドへ渡す一時的な環境を作る。現在のシェル変数は保持される。
詳細解説
LAB_MODE=prod bash -c 'printf "%s\n" "$LAB_MODE"'コマンド前の代入は、そのコマンドの環境だけに適用される。
LAB_MODE=prodは、続く外部コマンドbashへ渡す環境にだけ適用される。子がprodを表示した後も、親のLAB_MODEはdevのまま残る。親の変数がexport済みかどうかと、1回のコマンドに渡す値を分けて考える。
export LAB_MODE=prod; bash -c 'printf "%s\n" "$LAB_MODE"'現在のBashのLAB_MODEもprodへ変更するため要件に合わない。
export LAB_MODE=prodを親で実行すると、親の値もprodになる。子の表示だけは要件と同じでも、親のdevを保持する条件に合わない。子と親の両方の観測結果で判断する。
LAB_MODE=prod; bash -c 'printf "%s\n" "$LAB_MODE"'現在のBashの変数を変更し、exportされていなければ子Bashへも渡らない。
セミコロン前の代入は独立したコマンドなので、親の値をprodへ変える。子が何を表示するかは元のexport属性によって異なるが、親を保持しない点で要件に合わない。
bash -c 'printf "%s\n" "$LAB_MODE"' LAB_MODE=prod末尾の文字列は位置パラメータ$0となり、環境変数の代入にはならない。
bash -cではコマンド文字列後の最初の引数が子の$0になる。この位置のLAB_MODE=prodは通常設定では環境代入ではない。親で未exportなら子の値は空、export済みならdevを受け取る。
実際に確かめる
一時的な検証環境で実行できる例です。
LAB_MODE=dev
LAB_MODE=prod bash -c 'printf "child=%s\n" "$LAB_MODE"'
printf 'parent=%s\n' "$LAB_MODE"参考にした公式資料
期待される結果
child=prod
parent=dev理解のポイント
- コマンド前の変数代入
- 子プロセスの環境
- 親シェルの値の保持
確認時の注意
- 確認環境: Bash 5.2、通常設定の新規Bashプロセス。LAB_MODEは変更可能な通常変数とし、set -a/-kは無効で確認する。
- 普段の作業シェルではなく新規Bashで確認する。検証コマンドは子のprodと親のdevを順に表示する。
- この問題は通常設定の外部コマンドbashを扱う。既存のexport属性を仮定せず、未export/ export済みの両方で親の値が保持されるかを確認する。
基礎のおさらい
値の適用範囲を2か所で見る
仮想値dev/prodの例では、子がprodを表示したかだけでなく、その後の親がdevを保持したかを確認する。子への一時環境と親に残る代入を区別する。
export状態による誤答の違い
親の変数が未exportなら、単独の代入だけでは子に渡らない。export済みならその属性が残り得るため、子の表示だけを一律に断定しない。どちらでも親をprodへ変える案は要件を満たさない。
bash -cの引数の位置
文字列の前にある代入語と、文字列後の引数では役割が違う。後者の最初の引数は$0として使われ、$1とは区別する。