C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

C#での文字列検索

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■90366 / inTopicNo.1)  C#での文字列検索
  
□投稿者/ ameagari (1回)-(2019/03/04(Mon) 17:13:23)

分類:[C#] 

はじめまして。
C#での文字列検索についての質問です。

ある文字列の中から指定文字列を以下の4パターンで検索したいです。

指定文字列の
@先頭に単語境界あり、末尾に単語境界なし
A先頭に単語境界なし、末尾に単語境界あり
B先頭に単語境界あり、末尾に単語境界あり
C先頭に単語境界なし、末尾に単語境界なし

検索対象の文字列、指定文字列は英語、日本語、イタリア語などと多言語の文字です。

正規表現の\bを使ってやってみましたが、日本語検索の時に引っかかりません。

使用したパターンは
@string pattern = @"\b" + FindStr;
Astring pattern = FindStr + @"\b";
Bstring pattern = @"\b" + FindStr + @"\b";
Cstring pattern = FindStr;

検索処理は以下を使いました。
Regex.Matches(str, pattern, RegexOptions.IgnoreCase | RegexOptions.ECMAScript)

・str = AreA bAre ArenA mAre A bdc A
 FindStr = A
 では、@〜Cのパターンで、すべてのAを検索できました。

・str = A4あA5あA0あA6あA7あA2あ A1 ああ A3
 FindStr = A0、A1、...、A7
 では、@〜Cのパターンで、A0〜A7を検索できました。

・str = 先頭あワードあ文字あ境界あ以外あまたはあ 列 ああ 行
 FindStr = 文字、列、または、行、先頭、ワード、境界、以外
 では、
 @のパターンで、「先頭」、「境界」を検索できません。
 Aのパターンで、「ワード」、「以外」を検索できません。
 Bのパターンで、「列」、「行」を検索できません。
 Cのパターンで、「文字」、「または」を検索できました。


@日本語検索の場合、単語の境界というものがないでしょうか?
A正規表現のパターンを変えれば、4パターンでの検索ができますでしょうか?
 もしできるなら、どう書けば良いでしょうか?
B正規表現に拘っていませんので、もし正規表現できないのであれば、
 C#で他に単語の境界がわかる方法がありますでしょうか?

C#が詳しくなくて、質問内容もわかりにくいと思いますが、
ご教授をお願いいたします。

引用返信 編集キー/
■90367 / inTopicNo.2)  Re[1]: C#での文字列検索
□投稿者/ Azulean (1038回)-(2019/03/04(Mon) 21:24:17)
2019/03/04(Mon) 21:26:24 編集(投稿者)

No90366 (ameagari さん) に返信
> @日本語検索の場合、単語の境界というものがないでしょうか?

正規表現はあくまで文字だけで完結する場合のみだと考えてください。

日本語は文字・文字種だけでは単語の区切りが判別できず、意味を解釈する必要があります。
よって、正規表現で単語の境界を扱うことはできません。


「形態素解析」という言葉で学ぶ領域になります。
望む結果を得ることは、簡単ではないかもしれないので覚悟して臨んでください。

追記
英語がかんたんなのは、単語の区切りにほぼ空白が存在するから。
日本語にそんな前提はなく、ひらがなや漢字といった文字種の切り替わりも単語の区切りにならないので、文字だけで評価する正規表現では実現できない。
引用返信 編集キー/
■90368 / inTopicNo.3)  Re[1]: C#での文字列検索
□投稿者/ Hongliang (764回)-(2019/03/04(Mon) 21:49:09)
https://docs.microsoft.com/en-us/dotnet/standard/base-types/anchors-in-regular-expressions#word-boundary-b
\bの定義は、「\wと\Wの境界」です。
https://docs.microsoft.com/en-us/dotnet/standard/base-types/character-classes-in-regular-expressions#word-character-w
\wの定義は、ECMAScript互換の場合、[a-zA-Z_0-9] です。
\Wの定義はそれ以外である [^a-zA-Z_0-9] です。
つまりアルファベット・アンダースコア・数字(どれもいわゆる半角のみ)とそれ以外の境界が、\bにマッチします。

日本語は分かち書きしない言語であるため、機械的に単語を抽出することが極めて困難です。
異なる位置で分けてもどちらも正しいというものすらあります。例えば「アフガン航空相撲殺される」は「アフガン/航空相/撲殺/される」でも「アフガン/航空/相撲/殺される」でも個々の単語は成立します。
そういう文章を解析するのが形態素解析というやつで、世には様々なライブラリが存在しているようです。
// 私はやったことありませんので何も言えません。

あるいは、今回の質問における"単語"の意味によってはもっと単純な話になるのかも知れませんが。
引用返信 編集キー/
■90369 / inTopicNo.4)  Re[1]: C#での文字列検索
□投稿者/ キングダム (8回)-(2019/03/04(Mon) 22:25:18)
No90366 (ameagari さん) に返信

日本語の文は格関係によって名詞と述語の関係が決まるので
雑なものでよければ格助詞を単語の区切りとみなせばよいのじゃないでしょうか

例えば次の文だと
昔々、あるところにおじいさんとおばあさんが住んでいました

格助詞「に、と、が」によって分けてこんな感じです
昔々、あるところ/おじいさん/おばあさん/住んでいました

「〜は」「〜も」といった係助詞や句読点も追加したが良いかもしれないですね
100%は無理なのでどの辺りで妥協するかということになるかと思います


引用返信 編集キー/
■90370 / inTopicNo.5)  Re[2]: C#での文字列検索
□投稿者/ ameagari (2回)-(2019/03/05(Tue) 09:14:54)
皆さん、ご回答ありがとうございました。

日本語の単語境界チェックは難しいということですね。
やりたいことをもう一回考えたいと思います。

ありがとうございました。
解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ