正規表現ライブラリ   2013/11/15


1. 使用方法

1.1 正規表現オブジェクトを作成する

onig_pattern_compile(+PATTERN, -REGEX)

PATTERN: 正規表現パターン (アトム/文字列)
REGEX:   作成された正規表現オブジェクト

不正なパターンを指定すると失敗する。

例： onig_pattern_compile('^[a-z]+', REGEX).

注： 正規表現パターンの文法については、以下を参照。
     http://www.geocities.jp/kosako1/oniguruma/doc/RE.ja.txt
     これと同じファイルが、インストールしたときの
     .../oniguruma/doc/RE.jaファイルとして存在するので
     これを参照しても良いが、EUC-JPで書かれている。


1.2 使用しなくなった正規表現オブジェクトを開放する

onig_pattern_free(+REGEX)

たくさん正規表現を使用するのでなければ、
実行しなくてもよいかもしれない。


1.3 不正な正規表現パターンのエラー情報取得

onig_pattern_error_info(+PATTERN, -ERR)

PATTERN: 正規表現パターン (アトム/文字列)
ERR:     エラー情報のアトム

例： onig_pattern_error_info('(', ERR).
     ==> ERR = 'end pattern with unmatched parenthesis'


1.4 検索対象文字列オブジェクトを作成する

onig_make_target_string(+STRING, -TARGET_STRING)

STRING: AZ-Prologの文字列(リスト)/アトム
TARGET_STRING: 正規表現ライブラリで対象とする文字列オブジェクト

このライブラリはPrologの文字列を直接検索できないので、
この述語によって変換したものを作成する必要がある。

改行文字(列)の変換も同時に行われる。
"\r\n" ==> "\n"
  31   ==> "\n"    (31: AZ-Prologの改行コード)

対象文字列オブジェクトに対する操作、検索結果のcapture(捕獲)文字列
に改行が含まれる場合には、上記の改行コードの変換が行われたものが
入っている。


1.5 検索対象文字列オブジェクトを開放する

onig_free_target_string(+TARGET_STRING)


1.6 検索対象文字列オブジェクトの一部分を返す

onig_target_string_part(+TARGET_STRING, +START, +END, -PART_STRING)

TARGET_STRING: 検索対象文字列オブジェクト
START:         開始位置 (先頭は0)  バイト単位
END:           終了位置 (この位置の文字は含まれない)  バイト単位
PART_STRING:   部分文字列 (AZ-Prologのリスト)

この述語は検索に直接必要なわけではない。


1.7 正規表現検索を実行

1.7.1 onig_search/7

onig_search(+REGEX, +TARGET_STRING, +START, +END, -MSTART, -MEND, -CAPTURES)

REGEX:         正規表現オブジェクト
TARGET_STRING: 検索対象文字列オブジェクト
START:         検索開始位置 (先頭は0)   バイト単位
END:           検索終了位置 (文字列の終わりまでなら未定義でもよい) バイト単位
MSTART:        マッチした文字列の開始位置  バイト単位
MEND:          マッチした文字列の終了位置  バイト単位
CAPTURES:      captureグループ(捕獲式集合)のcapture文字列のリスト

全くマッチしなかった場合には、失敗する。
!!! この述語は非決定性ではない。 !!!

captureグループの中で、マッチしていないグループに対しては
文字列ではなく'non'というアトムがセットされる。

例：
正規表現が '(a+)|(b+)'、文字列が "bbbb  aaaa"の場合、
(b+)のほうにマッチして返るので、(a+)にはマッチしない。
この場合、CAPTURESには、[non, [98,98,98,98]]がセットされる。


1.7.2 onig_search_success/8

onig_search_success(+REGEX, +TARGET_STRING, +START, +END, -MSTART, -MEND,
                    -CAPTURES, -NEXT)

REGEX, TARGET_STRING, START, END, CAPTURES: onig_search/7と同じ。

マッチしたとき
MSTART: onig_search/7と同じ
MEND:   onig_search/7と同じ
NEXT:   マッチした長さが０より大きいとき
          --> MENDと同じ値
        マッチした長さが０のとき
          --> MENDの次の文字 (次の位置が文字列の範囲外なら、endアトム)

マッチしなかったとき
MSTART: nonアトム
MEND:   nonアトム
NEXT:   endアトム

!!! この述語は非決定性ではない。 !!!

マッチしなくても失敗しない。
マッチしたとき、次の開始位置を返すので、
文字列全体に対して繰り返して実行するとき便利。

注：
NEXTで、MENDの位置を返すというのは、全ての
マッチの可能性を調べるのであれば正しくない。
しかし現実の処理としてはこれで十分。


1.8 onig_version/1

   onig_version(-VERSION)

   VERSION: バージョン情報を示すアトム

   バージョン情報を取得する。

   例: 'oniguruma-ext: 0.5, oniguruma: 5.9.5'

-----------------------------------------------------------


2. 使用例

単純検索、連続検索、ntellとの速度比較。

%% simple match %%
test1(PATSTR, STRING):-
  onig_pattern_compile(PATSTR, REGEX),
  test1_1(REGEX, STRING),
  onig_pattern_free(REGEX).

test1_1(REGEX, STRING):-
  onig_make_target_string(STRING, TSTRING),
  test1_2(REGEX, TSTRING),
  onig_free_target_string(TSTRING).

test1_2(REGEX, TSTRING):-
  onig_search(REGEX, TSTRING, _, _, MS, ME, CAPTURES), !,
  write('match range: '), write([MS, ME]), nl,
  write('captures: '), write(CAPTURES), nl.
test1_2(REGEX, TSTRING).

:- test1('', "").
:- test1('a', "a").
:- test1('abc', "abc").
:- test1('abc', "zzsdfe grehghabfabcdegh rraaabc").
:- test1('a(.*)', "abc").
:- test1('a(?:.*)', "abc").   %% don't capture group
:- test1('(a+)|(b+)', "bbbb  aaaa").
:- test1("^[ \t]*subnet mask[ \t]*=[ \t]*([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)",
        " subnet mask =  255.255.128.0 ").


%% sequence of match %%
test2(PATSTR, STRING):-
  onig_pattern_compile(PATSTR, REGEX),
  test2_1(REGEX, STRING),
  onig_pattern_free(REGEX).

test2_1(REGEX, STRING):-
  onig_make_target_string(STRING, TSTRING),
  test2_2(REGEX, TSTRING),
  onig_free_target_string(TSTRING).

test2_2(REGEX, TSTRING):-
  test2_search(REGEX, TSTRING, 0).

test2_search(REGEX, TSTRING, end):- !.
test2_search(REGEX, TSTRING, FROM):-
  onig_search_success(REGEX, TSTRING, FROM, _, MS, ME, CAPTURES, NEXT),
  test2_result(MS, ME, CAPTURES),
  test2_search(REGEX, TSTRING, NEXT).

test2_result(non, _, _):- !.
test2_result(MS, ME, CAPTURES):-
  write('match range: '), write([MS, ME]), nl,
  write('captures: '), write(CAPTURES), nl.

:- test2('zzz', "abc").
:- test2('abc', "abcababcdefabccab").
:- test2('([0-9a-fA-F:]+)', " ab:05:f4:18:2e:3c    ").


%% compare performance %%

pf(ntell, PAT, S):-
  pattern_compile(PAT, REG),
  rexpl_members0(S, REG, G, E, B, SUB),
  % write(G), nl, write(SUB), nl,
  fail.
pf(ntell, PAT, S).

pf(oniguruma, PATSTR, STRING):-
  onig_pattern_compile(PATSTR, REGEX),
  pf1(REGEX, STRING),
  onig_pattern_free(REGEX).

pf1(REGEX, STRING):-
  onig_make_target_string(STRING, TSTRING),
  pf2(REGEX, TSTRING, 0),
  onig_free_target_string(TSTRING).

pf2(REGEX, TSTRING, end):- !.
pf2(REGEX, TSTRING, FROM):-
  onig_search_success(REGEX, TSTRING, FROM, _, MS, ME, CAPTURES, NEXT),
  pf2(REGEX, TSTRING, NEXT).

npf(N, TIME, ENGINE, PAT, S):-
  NN is N - 1,
  TS is cputime,
  repeat(I),
  pf(ENGINE, PAT, S),
  I =:= NN, !,
  TE is cputime,
  TIME is TE - TS.

comp(N, PAT, S):-
  write('ntell start'), nl,
  npf(N, TIME_NTELL, ntell, PAT, S),
  write('ntell end'), nl,
  write('time(sec.): '), write(TIME_NTELL), nl,
  write('oniguruma start'), nl,
  npf(N, TIME_ONIG, oniguruma, PAT, S),
  write('oniguruma end'), nl,
  write('time(sec.): '), write(TIME_ONIG), nl.

:- comp(200,
"^[ \t]*[0-9]+[ \t]+1/2[ \t]+NA[ \t]+[0-9]+[ \t]+[0-9]+[ \t]+([0-9]+)[ \t]+([0-9a-zA-Z]{2} [0-9a-zA-Z]{2} [0-9a-zA-Z]{2} [0-9a-zA-Z]{2} [0-9a-zA-Z]{2} [0-9a-zA-Z]{2})[ \t]+Dynamic",
"Record OLT LPort ONU id LLID   VID  Mac_Adress     Type
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Static
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Static
  1     1/2    NA      0    1   101   00 07 ba 34 00 45 Dynamic
  2     1/2    NA      0    1   101   00 02 8a b5 b4 11 Dynamic
  3     1/2    NA      3    3   102   00 07 ca 77 00 42 Dynamic
  4     1/2    NA      2    2   102   00 07 da 77 00 43 Dynamic
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Static
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Static
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Static
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Static
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Static
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Dynamic
  6     1/2    NA      4    4   104   00 07 ea 8f 99 34 Dynamic
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Static
  7     1/2    NA      5    5   105   00 07 ea 8f 99 35 Dynamic
  8     1/2    NA      6    6   106   00 07 ea 8f 99 36 Dynamic
  9     1/2    NA      7    7   107   00 07 ea 8f 99 37 Dynamic
 10     1/2    NA      8    8   108   00 07 ea 8f 99 38 Dynamic
 11     1/2    NA      9    9   109   00 07 ea 8f 99 39 Dynamic
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Static
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Static
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Static
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Static
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Static
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Static
 12     1/2    NA     10   10   110   00 07 ea 8f 99 3a Dynamic
 13     1/2    NA     11   11   111   00 07 ea 8f 99 3b Dynamic
 14     1/2    NA     12   12   112   00 07 ea 8f 99 3c Dynamic
 15     1/2    NA     13   13   113   00 07 ea 8f 99 3d Dynamic
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Static
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Static
 16     1/2    NA     14   14   114   00 07 ea 8f 99 3e Dynamic
 17     1/2    NA     15   15   115   00 07 ea 8f 99 3f Dynamic
 18     1/2    NA     16   16   116   00 07 ea 8f 99 90 Dynamic
 19     1/2    NA     17   17   117   00 07 ea 8f 99 91 Dynamic
 20     1/2    NA     18   18   118   00 07 ea 8f 99 92 Dynamic
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Static
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Static
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Static
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Static
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Static
  5     1/2    NA      1    1   103   00 07 ea 8f 99 30 Static
BBS1000_TOKYO_01> ").
