C で正規表現!

Ruby は超強力な正規表現エンジンである鬼雲を搭載しています。試しに鬼雲 (鬼車) の C API を使って、複雑なパターンマッチを試してみました。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "oniguruma.h"

int main(int argc, char *argv[])
{
  int rv;
  regex_t *re;
  OnigErrorInfo einfo;
  UChar *start, *end, *range;
  OnigRegion *region = onig_region_new();

  /* Programming Ruby 1.9 & 2.0 より */
  /* 正規表現パターン */
  UChar *pat = (UChar*)
      "(?<subject>   cat   | dog    | gerbil   ){0}"
      "(?<verb>      eats  | drinks | generates){0}"
      "(?<object>    water | bones  | PDFs     ){0}"
      "(?<adjective> big   | small  | smelly   ){0}"
      "(?<opt_adj>   (\\g<adjective>\\s)?      ){0}"
      "The\\s\\g<opt_adj>\\g<subject>\\s\\g<verb>\\s\\g<opt_adj>\\g<object>";
  /* マッチ対象 */
  UChar *str = (UChar*)"The cat drinks water";

  /* 正規表現オブジェクトの生成 */
  (void)onig_new(&re, pat, pat + strlen((char*)pat),
    ONIG_OPTION_DEFAULT | ONIG_OPTION_EXTEND,
    ONIG_ENCODING_UTF8,
    ONIG_SYNTAX_RUBY,
    &einfo);

  start = str;
  end = range = str + strlen((char*)str);

  /* パターン検索 */
  rv = onig_search(re, str, end, start, range, region, ONIG_OPTION_NONE);
  if (rv >= 0) {
    UChar *name = (UChar*)"subject";
    int *nsubject;
    /* 名前付きグループから番号 (の配列) を得る */
    rv = onig_name_to_group_numbers(re, name, name + strlen((char*)name),
        &nsubject);
    assert(rv > 0);
    char *subject = strndup((char*)(str + region->beg[nsubject[0]]),
        region->end[nsubject[0]] - region->beg[nsubject[0]]);

    name = (UChar*)"verb";
    int *nverb;
    rv = onig_name_to_group_numbers(re, name, name + strlen((char*)name),
        &nverb);
    assert(rv > 0);
    char *verb = strndup((char*)(str + region->beg[nverb[0]]),
        region->end[nverb[0]] - region->beg[nverb[0]]);

    /* 結果の表示 */
    printf("%s\n\n", (char*)str);
    printf("subject: %s\nverb: %s\n", subject, verb);

    free(subject);
    free(verb);
  }

  onig_region_free(region, 1);
  onig_free(re);
  onig_end();

  return 0;
}

実行結果:

The cat drinks water

subject: cat
verb: drinks

これは凄い。しかし、簡単な文法で同じことができちゃうあたり、Ruby ってよく出来てるんだなあ…なんて思ったり。

ちなみに、Programming Ruby 1.9 & 2.0 は今どきの Ruby の機能を丁寧に解説していて勉強になります。

http://pragprog.com/book/ruby4/programming-ruby-1-9-2-0

(コウヅ)

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中