Yash 2 その 287: [[ コマンド構文
Yash に [[ コマンド構文を取り入れることを検討する。
これまでは test 組込みコマンドがあるから [[ 構文は不要としてきたが、bash も zsh も ksh もサポートしてゐる機能なので POSIX 規格に定義されてゐないにも拘はらずいろいろなスクリプトで使はれてゐる。例へば一般的な Linux ディストリビューションで /etc/profile.d ディレクトリーに置かれてシェル初期化時に読み込まれるスクリプトで [[ 構文が使はれることがある。実用上不便なので、yash でもサポートできれば便利だらう。
[[ 構文の正確な仕様は bash のマニュアルにも ksh のマニュアルにも詳しく書かれてゐない。Mksh のマニュアルにはそれなりに詳しく test 組込みコマンドと [[ 構文との違ひが記されてゐる。Zsh のマニュアルにも少し説明がある。
特記なき限り、以下の説明は bash, zsh, ksh, mksh のいづれにも当てはまる。
- [[ 構文では各単語は四種展開後にパス名展開及び単語分割が行はれない。
- 各演算子は [[ 構文が評価されるときではなく構文解析されるときに構文解析される。もちろんこのタイミングでは各単語の四種展開や引用符除去はまだ行はれてゐない。従ってクォートされた演算子は演算子と見做されない。
- 各演算子がシェルスクリプト全体の構文の一部として LL パーサーによって解析されることの帰結として、演算子に見えるトークンは常に演算子と解析される。例へば
[[ -a = -a ]]
は-a
といふ二つの文字列を=
演算子で比較するのではなく-a
単項演算子の誤った使ひ方と解析される (Zsh はもう少し賢くて[ -a = -a ]
と同じ結果が得られる)。[[ -n && ]]
では-n
の被演算子が文字列でないといふ構文エラーになる。 - Zsh はハイフンで始まるトークンを常に演算子と見做し、演算子の分類を実行時まで遅延する様である。例へば
[[ -# ]]
は未定義の演算子による実行時エラーとなる (構文エラーではない)。Bash, ksh, mksh ではこれは単なる文字列と見做される。 <
および>
は [[ 構文の中ではリダイレクト演算子ではなく文字列比較の演算子として扱はれる。一方<>
や;
をクォート無しで使ふと構文エラーとなる。
- 各演算子がシェルスクリプト全体の構文の一部として LL パーサーによって解析されることの帰結として、演算子に見えるトークンは常に演算子と解析される。例へば
- 論理積および論理和の演算子として
&&
と||
を使用する。&&
と||
は短絡評価なので右辺の評価 (パラメータ展開や数式展開を含む) は必要な場合のみ行はれる。-a
および-o
は論理積および論理和の二項演算子としては使用できない。これは-a
および-o
の多義性を排除して構文解析をしやすくするために事実上必須の仕様である。- なほ、逆に test コマンドで
&&
と||
を演算子として使ふこともできない。
- 文字列比較演算子
=
,==
,!=
の右辺 (のクォートされてゐない部分) はパターンと見做され、左辺に対してパターンマッチングされる。右辺に含まれるパラメータ展開の結果がパターンとなる場合も (クォートされてゐなければ) パターンマッチングされる。ただしデフォルトの zsh はパラメータ展開の結果がパターンとなる場合でもマッチングを行はない (ファイル名展開と同様)。 - [[ 構文では、
-eq
等の数値比較演算子の被演算子は数式として解析される。例へば[[ '1 + 1' -eq 2 ]]
が成功する。Bash と zsh は、test 組込みコマンドでは被演算子は単なる整数でなければいけない。Ksh と mksh は test 組込みコマンドでも被演算子を数式として解析する。 - 正規表現マッチング演算子
=~
が bash, zsh, ksh で使用できる。Ksh は test 組込みコマンドでもこの演算子を使用できる。Mksh は正規表現マッチングをサポートしてゐない。
さて、yash に [[ 構文を実装するにはどの様な設計にすべきか。他のシェルは [[ 構文の中身の構文解析をシェルスクリプト全体の構文解析の一環として行ってゐる様だ。それを真似ようとすると、yash の手書きの再帰降下型パーサーに test 組込みコマンドで使へるたくさんの演算子を対応させねばならず大変だ。できれば ]]
がどこにあるかだけを構文解析時に見付けて、中身の構文解析は (test 組込みコマンドと同様に) コマンド実行時まで遅延させたい。幸ひ、bash, zsh, ksh は ]]
を常に演算子と見做す様なので [[ -n ]] ]]
の様な紛らはしいケースはエラーとして良い。とは言へ、[[ = = ]]
の様な構文エラーが実行するまで判らないといふのでは明らかに他のシェルと挙動が異なってしまふ。となると、やはりまじめにパーサーを実装しなければならないのだらうか。
| 固定リンク
コメント