#navi(全般) #contents //////////////////////////////////////////////////////////////////////////// *構文解析のおおまかな順序 [#sdbf768f] +環境変数の置換、引数の置換、if/for/( ) 等の構造を持った文の構文解析、およびリダイレクトの判断等が同順序 +for 制御変数の置換 +環境変数遅延展開の置換 +コマンド名、リダイレクトファイル名の確定とリダイレクト・パイプのオープン +(コマンドの探索と実行) //////////////////////////////////////////////////////////////////////////// *構文解析 [#m8bf1483] 以下の解析が同時になされる。 **行末の ^ による継続行処理 [#c1b965a8] 行末がクォートされていない ^ である場合は次の行とつなげて、構文解析を続ける。 **文の区切りの認識 [#b334b9a7] 1行に複数の文を書く場合がある。クォートされていない & && || | を区切りと 見なしてその前後で、それぞれ構文解析を行う。 **括弧による複合文の認識 [#u30a3bf5] 改行や上記文区切り記号で区切られた複数の文を、クォートされていない括弧で 囲んで一つの文として扱う。プログラミング言語でよくある { } や begin/end do/end などと同じ。~ 括弧を開いたまま閉じる括弧がなくバッチスクリプトのファイルが終わった場合は、 開く括弧以降が構文解析できないため全て捨てられる。 **if/for という構造を持った構文の解析 [#u62bb045] 文頭が if か for ならそれぞれの構文に従って解析を進める。 **リダイレクトの処理 [#ne4afac4] クオートされていない < > >> があればその次のトークンをファイル名と見なして リダイレクト指定であるというマーキングを行う。実際のファイルオープンは まだ先で環境変数遅延展開の後、コマンド実行の前である。~ [[全般/ファイルディスクリプタとリダイレクト]]も参照。 **2個連続した % の1個の % への置換 [#s0e0ca3e] バッチスクリプトであれば連続した % は1つにして、環境変数展開には使わない。 **% による環境変数の展開 [#iabd15b7] 単独の % がありその後に % が出てくれば、環境変数展開と見なす。 :~ が途中にあれば部分文字列の修飾で、: = がこの順に途中にあれば文字列置換の 修飾である。 **単独の % の削除 [#ea9702e9] 対応する % が行内に無い単独の % を削除する。 **空白文字の無視 [#f119fd64] 構文解析時にいくつかの箇所で、クォートされていない = ; , は空白と同じ 扱いを受ける。~ 行頭、リダイレクト記号とファイル名の間、if 構文の比較の == 以外の場所、 for 構文。 **^ による特殊文字のクォート [#af966e05] ^ の次の特殊文字 ^ " < > & | ( ) = ; ,の特殊な意味を失わせる。 また、リダイレクト記号の直前の1桁の数字も ^ によってクォートされると ファイルディスクリプタ番号としての意味を失う。 これら以外の文字が続く場合は ^ が削除される。 ! はこの時点では特殊文字ではないので、^! と書いても遅延展開の意味を失わない。 **" による文字列のクォートと1トークン化 [#a46ff77b] クォートされていない " が出てきたらそこから次の " または行末までの % 以外の全ての特殊文字が特殊な意味を失う。 途中に空白や、構文解析上空白と見なされる場合のある = ; , があっても トークンの区切りとはみなさず複合した1つのトークンとみなす。~ 複合したトークンとして扱われて意味があるのは、リダイレクト記号の次、 if 構文の比較対象、for 構文の in ( ) の括弧の中。 //////////////////////////////////////////////////////////////////////////// *環境変数遅延展開の置換 [#jbf7c2b6] 遅延展開が有効でかつ ! が行内にあるとき、以下の処理が行われる。 ! が無い行については何もなされない。 [[コマンド別/set]]の「set /a 特殊記号の演算子」も参照。 **^ による ^ ! のクォート [#j4da5af5] % と違って文字として ! を残したい場合 !! と書くのは駄目で両方消える。 ! を環境変数展開に使わず普通の文字として扱いたい場合は ^ でクォートする。 ただし、^ は構文解析時の特殊文字でもあるので、この時点で単独の ^ が必要なら 最初に ^^ と書いておくと構文解析時に1つの ^ になる。~ つまり単独の ! 文字が必要なら、^^! と書き、単独の ^ が必要なら ^^^^ と書く。 **! による環境変数の展開 [#gd37d352] 単独の ! がありその後に ! が出てくれば、環境変数展開と見なす。 :~ が途中にあれば部分文字列の修飾で、: = がこの順に途中にあれば文字列置換の 修飾である。 **クォートされなかった ! の削除 [#w856d6a5] クォートされていない残った ! を削除する。 //////////////////////////////////////////////////////////////////////////// *コマンド実行時の特殊記号の扱い [#c8b83115] コマンド実行時には、構文解析時の各特殊記号にどのような意味を与えるのかは 各コマンドの解釈次第である。 例: ファイル A から " を含む行を検索し、ファイル B に入れることを意図して、次のように書いたとする。 findstr """ A >B 構文解析時には、3つ目の " から行末までは文字をクォートしているので、>B はりダイレクトでなくそのままの文字列として扱われる。~ findstr コマンドは """ を1つの " として検索文字として扱い、 A と >B を検索対象のファイル名として扱う。~ つまり、A と >B は構文解析時は引用符の中、コマンド実行時は引用符の外である。~ その結果として、ファイルA中で " を含んだ行があればそれを表示した後、 FINDSTR: 開くことができません (>B) というエラーになる。~ 意図どおりの結果を得るには、リダイレクトが " " の中に入らなければ良いので、 findstr >B """ A findstr < A > B """ 等と書けばよい。 //////////////////////////////////////////////////////////////////////////// #navi(全般)