コマンド置換のエイリアスはどのように機能する必要がありますか?

コマンド置換のエイリアスはどのように機能する必要がありますか?

さまざまなシェルを使用して複数のスクリプトをテストしましたが、結果はさまざまでした。

# test 1
foo(){ echo $(al);}
alias al='echo 123'
foo

# test 2
alias al='echo 123'
foo(){ echo $(al);}
alias al='echo abc'
foo

# test 3
alias foo='echo $('
echo $(foo echo '123'))

# test 4
alias foo='echo $('
echo "$(foo echo '123'))"

# test 5
alias bar='echo 123)'
echo $(bar
bash 5.1.16 (--posix を使用) 昆山 2020.0.0 zsh 5.9 ダッシュ 0.5.12 ヤッシュ 2.53
テスト1 123 123 123 卵:見つかりません そのようなコマンドはありませんal
テスト2 アルファベット アルファベット アルファベット 123 123
テスト3 予期しないマーク) )事故 123 123 123
テスト4 123 123 123 123 123
テスト5 予期しないファイルの終わり (耐え難い コマンドが見つかりません:barecho 123 123

したがって、基本的にbashとkshは遅延エイリアス置換を実行し、dashとyashは劣性エイリアス置換を実行します。 zshの動作は説明が少し難しいです。特にコマンドを見つけようとすると、5の場合はさらにそうですbarecho

テスト4は、すべてのシェルが一致する唯一のケースです。これは混乱しています。なぜならPOSIX規格 2.2.3二重引用符説明する:

"$(" と一致する ")" の間に含まれる引用符付き文字列の入力文字は、二重引用符の影響を受けてはいけませんが、代わりに単語が展開されたときに出力が "$(...)" を置き換えるコマンド定義する必要があります。 。一致する「)」を見つけるには、トークン認識のトークン化規則(別名置換の別名置換を除く)を繰り返し適用する必要があります。

標準では、二重引用符内のコマンド置換で一致する括弧を見つけようとすると、シェルはエイリアス置換を使用しないでください。ただし、すべてのシェルは二重引用符内にエイリアス置換を使用し、一部のシェルは二重引用符なしでは使用しません。

問題は、特定の状況で特定のシェルが間違っているのか、それとも別のものかです。つまり、この状況で正しい行動が何であるかを示すいくつかの規則がありますか?

関連情報