プロが教えるわが家の防犯対策術!

C言語版の鬼車ライブラリを利用して、ある検索プログラムを作成したいのですが、
1点質問です。

以下のような例文があるおします。
(例)
--
最初の試験、二番目の試験、三番目の試験、最後の試験

--

onig_search()を使用して上記から”試験”のすべての検出箇所を調べたいのですが、
パターンに”試験”を指定してonig_search()をコールしても最初の1件目のみしか
検出しません。

特殊なオプションが必要なのでしょうか?
それとも、パターン(正規表現)の書き方が誤っているのでしょうか?

問題が解決せず非常に困っています。
どなたか、解決策をお持ちの方は知恵を貸してください。

A 回答 (4件)

#1/3です。

少々訂正。

> startを前回のヒット位置(onig_searchの戻り値)+strへずらしながら

startを前回のヒット位置(onig_searchの戻り値) + str 「+ strlen(pattern)」へずらしながら

です。でないと無限ループしてしまいますね。
    • good
    • 0
この回答へのお礼

D-Matsu さん

回答ありがとうございます。

> 改めて仕様を読み直してみたら、戻り値が最初のヒット位置というだけで、それとは別に引数の構造体regionにヒット数と開始・終了アドレスが入るんですね。
> 読み違えてました。失礼。

確認ありがとうございます。

> さて、それを踏まえて例示されたコードですが、間違いはなさそうに見えます。
> こちらでも以下の環境下で試してみたのですが、
>
> ・OpenSuSE 11.4 x64
> ・gcc 4.5.1
>
> 配布元の最小限使用例に対してonig_newのencをUTF8に変えてpatternとstrを質問と同じ状態にしてみただけのコードで再現しますね……。
> ASCIIに直して追試したらUTF-8と同じ結果が出たので、なんとなくですがUTF-8の処理が甘いような印象があります。
>
> 「とりあえず回避」というやり方ですが、startを前回のヒット位置(onig_searchの戻り値)+strへずらしながらヒットしなくなるまで一つずつ拾っていく手かと思います。

すいません。再現確認までして頂いて感謝します。
そうですよね。。。
私もこの方法しかないと考えていました。
入力情報(検索対象とパターン)はファイルから読み込む設定値なので、プログラムを変えずに対応できれば
と思っていたのですが。。。了解です。
当初、鬼車ライブラリの使用方法の誤りかと思っていのたですが、
そうでもなさそうですね。
深夜に対応ありがとうございました。

お礼日時:2011/06/23 09:52

#1です。



改めて仕様を読み直してみたら、戻り値が最初のヒット位置というだけで、それとは別に引数の構造体regionにヒット数と開始・終了アドレスが入るんですね。
読み違えてました。失礼。

さて、それを踏まえて例示されたコードですが、間違いはなさそうに見えます。
こちらでも以下の環境下で試してみたのですが、

・OpenSuSE 11.4 x64
・gcc 4.5.1

配布元の最小限使用例に対してonig_newのencをUTF8に変えてpatternとstrを質問と同じ状態にしてみただけのコードで再現しますね……。
ASCIIに直して追試したらUTF-8と同じ結果が出たので、なんとなくですがUTF-8の処理が甘いような印象があります。

「とりあえず回避」というやり方ですが、startを前回のヒット位置(onig_searchの戻り値)+strへずらしながらヒットしなくなるまで一つずつ拾っていく手かと思います。
    • good
    • 0

#1 で書かれているように onig_search が


「start⇒rangeの間で最初にマッチした部分」を返す
というなら, それは「あなたが思っていた動作」に対して適切なコードではないと思われますが....

region の情報を使ってループ?
    • good
    • 0

まず「どう呼んでいるか」を提示してもらわないことにはどこが誤ってるのかも指摘しようがないんですが……



API仕様を読んだ感じでは「start⇒rangeの間で最初にマッチした部分」を返すようなので、「意図に合うような呼び出し方をしていない」線が濃厚じゃないかという気はするのですが。

この回答への補足

D-Matsuさん
回答ありがとうございます。

>まず「どう呼んでいるか」を~
ごもっともです。
コメント用に少し簡易的に編集していますが、
概ねこんな感じです。


--ココカラ--
unsigned char *start, *range, *end;// 正規表現用ポインタ
regex_t* reg = NULL; // 正規表現オブジェクト
OnigErrorInfoeInfo;
char *Target = "最初の試験、二番目の試験、三番目の試験、最後の試験";
char *pattern = "試験";

onig_new(&reg, (unsigned char*)pattern, (unsigned char*)pattern + strlen((char*)pattern),
ONIG_OPTION_MULTILINE | ONIG_OPTION_IGNORECASE,
ONIG_ENCODING_UTF8, ONIG_SYNTAX_DEFAULT, &eInfo);

end = (unsigned char*) (Target + strlen((char*)Target));
start = (unsigned char*) pTarget;
range = end;
region = onig_region_new();

onig_search(reg, Target, end, start, range, region, ONIG_OPTION_NONE);
--ココまで--

で、onig_search()の結果として、構造体regionに格納されるのですが、
該当数を示すregion->num_regs は1 になっており、初回該当の情報のみ格納されています。

確認した感じでは意図通りの呼び方に見えたのですが、
期待値と異なります。。。

どうでしょうか?

補足日時:2011/06/22 16:16
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!