2009-08-10
Captures captures();
括弧で指定したサブマッチの情報を、
ランダムアクセスレンジとして取得します。
第一要素はマッチ全体を表します。Example: foreach (m; match("abracadabra", "(.)a(.)")) { foreach (c; m.captures) write(c, ';'); writeln(); } // writes: // rac;r;c; // dab;d;b;
rfc3986 の付録 B. 正規表現による URI 参照の解析を使うと、
string uri = "http://www.ics.uci.edu/pub/ietf/uri/#Related"; auto r = r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?"; foreach (m; match(uri, r)) { int i = 0; foreach (c; m.captures) { writefln("$%d = %s",i++,c); } }
こんな風に書いたら、
$0 = http://www.ics.uci.edu/pub/ietf/uri/#Related $1 = http: $2 = http $3 = //www.ics.uci.edu $4 = www.ics.uci.edu $5 = /pub/ietf/uri/ core.exception.RangeError@std.regex(1667): Range violation
std.regex を見たら、
captures は サブマッチがすべてマッチしているのを前提にしているようだ。
Captures 構造体の front 関数の定義
Range front() { return input[matches[0].startIdx .. matches[0].endIdx];// startIdx endIdx が -1 になる可能性がある。 }
マッチしていないサブマッチも出力するなら、
captures でなく pmatch を使って書く必要がある。
string uri = "http://www.ics.uci.edu/pub/ietf/uri/#Related"; auto r = r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?"; foreach (m; match(uri, r)) { foreach (i,c; m.pmatch) { if(c.startIdx != -1) { writefln("$%d = %s",i,m.input[c.startIdx..c.endIdx]); }else{ writefln("$%d = <undefined>",i); } } }
出力結果
$0 = http://www.ics.uci.edu/pub/ietf/uri/#Related $1 = http: $2 = http $3 = //www.ics.uci.edu $4 = www.ics.uci.edu $5 = /pub/ietf/uri/ $6 = <undefined> $7 = <undefined> $8 = #Related $9 = Related
captures はマッチしたものだけを返すなら、
Captures 構造体の front 関数の定義はこうか?
Range front() { if(matches[0].startIdx == -1) popFront; return input[matches[0].startIdx .. matches[0].endIdx]; }
Captures 構造体の length 関数の定義はこうか?
size_t length() { size_t count foreach (m;matches) { if(m.startIdx != -1) count++; } return count; }