Yash 2 その 285: エイリアス置換の細かい挙動
バグ #37543 が見付かったのをきっかけに yash のエイリアス置換の挙動を再確認してゐたら、いろいろ怪しいところが出てきた。何が正しいのかを見極めるために、他のシェルの挙動を調べてまとめておく。
今回調べたシェルは yash 2.45, dash 0.5.9, bash 4.4(12), zsh 5.3.1, ksh 20120801, mksh 56b。Yash, bash, zsh は sh として動作させてゐる。それぞれの表では、Y がエイリアス置換が行はれることを、N が行はれないことを指してゐる。
POSIX 2016 には a resulting word that is identified to be the command name word of a simple command shall be examined to determine whether it is an unquoted, valid alias name.
と書かれており、単純コマンドのコマンド名に相当する単語のみがエイリアス置換の対象となると読めるが、実際にはほとんどのシェルでは関数定義文の先頭に来る関数名もエイリアス置換の対象となる。
alias foo='foo() { echo FOO; }; bar'
foo () { echo BAR; }
\foo
yash | dash | bash | zsh | ksh | mksh |
---|---|---|---|---|---|
Y | Y | Y | Y | Y | N |
POSIX はコマンド名に相当する単語のみがエイリアス置換の対象となると言ってゐるので、リダイレクトでファイル記述子を指定する数字は置換されない。
alias 1=0
1>/dev/null echo foo
yash | dash | bash | zsh | ksh | mksh |
---|---|---|---|---|---|
N | N | N | N | N | N |
同じ理由で、予約語も置換されない。
alias if='if echo IF;'
if true; then :; fi
yash | dash | bash | zsh | ksh | mksh |
---|---|---|---|---|---|
N | N | N | N | N | N |
エイリアス置換の結果が空白 (blank) で終はる場合、直後の単語もエイリアス置換の対象となることになってゐる。これは複合コマンドの中でも起きるのだらうか。Zsh のみ動作が違ってゐるが、置換が行はれてゐないとしたら出るはずのエラーが出ず謎。
alias forx='for x ' i='in 0'
forx i 1; do echo $x; done
yash | dash | bash | zsh | ksh | mksh |
---|---|---|---|---|---|
Y | Y | Y | N | Y | Y |
では、これが予約語の場合は?
alias forx='for x ' in='in 0'
forx in 1; do echo $x; done
yash | dash | bash | zsh | ksh | mksh |
---|---|---|---|---|---|
Y | N | N | N | N | N |
ファイル記述子は?
alias forx='for x ' 0='in I; do'
forx 0</dev/null echo $x; done
yash | dash | bash | zsh | ksh | mksh |
---|---|---|---|---|---|
N | N | N | N | N | N |
複合コマンドの外でも?
alias echo='echo ' 1=0
echo 1>/dev/null foo
yash | dash | bash | zsh | ksh | mksh |
---|---|---|---|---|---|
N | N | N | N | N | N |
話は変はって、エイリアスの値の中にある行連結は認識されるのか?
alias echo='\
echo\
' foo='\
bar\
'
echo \
foo
yash | dash | bash | zsh | ksh | mksh |
---|---|---|---|---|---|
N | Y | Y | Y | Y | Y |
といふことで、yash にはエイリアス置換すべきでない予約語を置換してしまふバグがあることが分かった。POSIX は reserved words in correct grammatical context shall not be candidates for alias substitution.
と言ってゐるので、yash 2.45 の挙動を正当化するのは難しからう。
また yash には値が空白で終はるエイリアス置換の後に行連結がある場合にその先の単語が置換の対象とならないバグもある(が、行連結の位置によっては発生しない)。
おまけとして、POSIX 範囲外の拡張であるグローバルエイリアスの扱ひも調べておく。これは yash と zsh のみ、非 POSIX モードで実行する。複合コマンドの予約語が現れるべき位置にグローバルエイリアスを置くことはできるか?
alias -g D=do
for i in 1; D echo $i; done
yash | zsh |
---|---|
N | Y |
| 固定リンク
コメント