Technology · 実用ガイド
Shell の「bad substitution」?書き換える前に interpreter と構文系を証明する
実際の launcher、parser と version、expansion の種類を固定し、Bash または portable sh の契約を選んで元の経路を再実行します。

「bad substitution」は式そのものが誤りだと証明しません。正しい Bash expansion でも sh、dash、古い Bash、source 元、wrapper が解析すれば失敗し、誤った ${command ...} は Bash でも失敗します。
command と stderr を保存し、execution route と effective interpreter を証明し、token を契約に照らして分類し、一つの branch だけ変更して同じ launcher を再実行します。
1. launch route と最初の error を固定する
完全な command、wrapper/scheduler 設定、cwd、environment 名、path、最初の stderr、exit status を保存し、direct、bash、sh、source、pipe を区別します。
/bin/sh の再リンクや shebang 削除、全 expansion 置換から始めると route の証拠が消えます。
2. 実際の interpreter と feature level を証明する
parent/child command line、wrapper の shell 設定、version probe を記録し、$SHELL を parser 証拠にしません。
shebang は OS が executable script を直接起動したときに有効で、source、sh -c、CI、cron は caller contract が所有します。
3. expression を分類する
portable parameter expansion と Bash-only replacement、substring、case、array を分け、正確な operator を公式 manual で確認します。
${ls ...} は parameter expansion と command substitution の混同です。$(...) を使い、eval で二重解析しません。
4. 一つの明示的 contract を選ぶ
Bash 必須なら全 wrapper と scheduler に対象 Bash を設定し、必要な version check を追加します。
POSIX sh 必須なら Bash-only syntax を仕様に基づく形へ置換し、混在させません。
5. 元 launcher で matrix 検証する
固定 fixture を dash -n、bash -n、production Bash、実 wrapper で試し、path、version、status、stdout、stderr を記録します。
元 route と期待 output が通過して acceptance とし、direct/source が異なるなら別 contract を宣言します。
