2011年11月25日金曜日

re2のxxxNの使い方

re2はGoogleが公開しているC++用の正規表現ライブラリです。速度も速い(らしい)し、ちゃんと日本語一文字も"."でマッチしてくれるので、社内でも好んで使われています。

たくさん機能があるようなんですが、Web上であまり情報がなかったり、詳細はheaderファイル見てね!みたいなことが書かれていて、なかなかマスターするのが難しいライブラリです。特に、マッチ箇所(いわゆるgroup)が複数あるときにどうすればいいのかすぐにわかりません。私も以前ここではまって、色々調べてどうにか動いたことがありました。ちょうど@chezouさんが困っていたようなので、メモのつもりで晒してみましょう。



説明するより、コード読むがはやし、ということでサンプルを!

#include <re2/re2.h>
#include <string>
#include <vector>
#include <iostream>

using namespace std;

int main() {
  string pat = "(.)(.)(.)(.)";
  string text = "hoge";
                                                                                                                                                                         
  re2::RE2 re(pat);
  re2::StringPiece input(text);
  int groupSize = re.NumberOfCapturingGroups();
  vector<re2::RE2::Arg> argv(groupSize);
  vector<re2::RE2::Arg*> args(groupSize);
  vector<re2::StringPiece> ws(groupSize);
  for (int i = 0; i < groupSize; ++i) {
    args[i] = &argv[i];
    argv[i] = &ws[i];
  }
  re2::RE2::PartialMatchN(input, re, &(args[0]), groupSize);
  for (int i = 0; i < groupSize; ++i)
    cout << ws[i] << endl;
}

基本的にxxxN関数を使えばOKのようです。まず、RE2オブジェクトのgroupの数はNumberOfCaptureingGroupsで取れます。xxxN関数には、書き込み先のArgへのポインタの配列を渡す必要があります。なので、Argポインタのvector(これを関数に渡す)と、Arg実態のvectorを作ります。実態の方には、それが書き込む先のStringPieceへのポインタを代入しておくといいようです。ここは、intポインタなどを代入すれば、intに変換されて代入されるでしょう。この辺は、なんとなく書いたのでもっと良い書き方があるのかもしれません。これでマッチさせれば、最終的にStringPieceのvectorに結果が代入されました。

0 件のコメント:

コメントを投稿