C# サンプル集 |
Visual Basic 中学校 > C# サンプル集 > C# サンプル集目次 >
文字列をあいまい検索する
2021/10/24
目次
「源○朝」を検索する (○は任意の一文字)
string value = "源実朝は源頼家の弟であり、源頼朝の子です。";
var results = System.Text.RegularExpressions.Regex.Matches(value, "源.{1}朝");
foreach (System.Text.RegularExpressions.Match result in results)
{
System.Diagnostics.Debug.WriteLine($"ヒット:{result.Value} 開始位置:{result.Index}");
}
これを実行すると次の通りに出力されます。
ヒット:源実朝 開始位置:0
ヒット:源頼朝 開始位置:13
「源○○」を検索する (○は任意の一文字)
string value = "源実朝は源頼家の弟であり、源頼朝の子です。";
var results = System.Text.RegularExpressions.Regex.Matches(value, "源.{2}");
foreach (System.Text.RegularExpressions.Match result in results)
{
System.Diagnostics.Debug.WriteLine($"ヒット:{result.Value} 開始位置:{result.Index}");
}
これを実行すると次の通りに出力されます。
ヒット:源実朝 開始位置:0
ヒット:源頼家 開始位置:4
ヒット:源頼朝 開始位置:13
「源頼朝」以外の「源○朝」を検索する (○は任意の一文字)
string value = "源実朝は源頼家の弟であり、源頼朝の子です。";
var results = System.Text.RegularExpressions.Regex.Matches(value, "源[^頼]{1}朝");
foreach (System.Text.RegularExpressions.Match result in results)
{
System.Diagnostics.Debug.WriteLine($"ヒット:{result.Value} 開始位置:{result.Index}");
}
これを実行すると次の通りに出力されます。
ヒット:源実朝 開始位置:0
「源頼朝」以外の「源○○」を検索する (○は任意の一文字)
string value = "源実朝は源頼家の弟であり、源頼朝の子です。";
var results = System.Text.RegularExpressions.Regex.Matches(value, "源(?!頼朝).{2}");
foreach (System.Text.RegularExpressions.Match result in results)
{
System.Diagnostics.Debug.WriteLine($"ヒット:{result.Value} 開始位置:{result.Index}");
}
これを実行すると次の通りに出力されます。
ヒット:源実朝 開始位置:0
ヒット:源頼家 開始位置:4
「…ed」で終わる英単語を検索する
string value = "Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived and so dedicated, can long endure.";
var results = System.Text.RegularExpressions.Regex.Matches(value, @"(\s|^)(\w+?ed)([\s\.,]|$)");
foreach (System.Text.RegularExpressions.Match result in results)
{
System.Diagnostics.Debug.WriteLine($"ヒット:{result.Groups[2].Value} 開始位置:{result.Groups[2].Index}");
}
これを実行すると次の通りに出力されます。
ヒット:engaged 開始位置:11
ヒット:conceived 開始位置:87
ヒット:dedicated 開始位置:104
メモ:正規表現の意味は次の通り。スペース(\s)または文頭(^)から開始し、文字(\w)が1つ以上(+)続き、最初の(?) ed の出現後 スペース(\s) または ピリオド(\.) または カンマ または 文末 があるもの。
メモ:正規表現に含まれる ( ) にマッチしたものは Groups[] で取得できます。Groups[0]は常に正規表現にマッチした全体を表し、Groups[2]は正規表現に含まれる 2つ目の ( ) 内にマッチしたものという意味になります。
メモ:edで終わる英単語を検索するもっと簡単な正規表現があるかもしれません。
メモ:単語の区切りによってはこの例の正規表現では抽出できない場合があります。たとえば、? や ! などで単語が区切られる場合にはこの例をそのまま使用しても対応できません。
「民…法」を検索する(…は0文字以上の文字)
この例のポイントは、「民」の次に出現する「法」までを検索する必要がある点です。このために最短一致の正規表現 ? を使用します。
なぜならこの例の文字列では「民法や商法の訴訟手続きは民事訴訟法」が「民…法」に合致するので、最短一致にしないと優先的にヒットしてしまうからです。最短一致を指定するかどうかは検索の要件次第です。
string value = "民法や商法の訴訟手続きは民事訴訟法で定めわれている。";
var results = System.Text.RegularExpressions.Regex.Matches(value, "民.*?法");
foreach (System.Text.RegularExpressions.Match result in results)
{
System.Diagnostics.Debug.WriteLine($"ヒット:{result.Value} 開始位置:{result.Index}");
}
これを実行すると次の通りに出力されます。
ヒット:民法 開始位置:0
ヒット:民事訴訟法 開始位置:12
メモ:"民.*?法" ではなく、"民.*法" で検索すると「民法や商法の訴訟手続きは民事訴訟法」のみヒットします。
先頭が「子」から始まる行を検索する
string value = "論語の文章は「子曰」から始まるものが多い。例を挙げてみる。\r\n" +
"子曰學而時習之不亦説乎\r\n" +
"子曰不患人之不己知\r\n" +
"この「子曰」は「孔子はおっしゃった」という意味なので、\r\n" +
"孔子以外の人物の発言は次のように当然異なる書き出しとなる。\r\n" +
"子貢問曰貧而無諂富而無驕何如";
var results = System.Text.RegularExpressions.Regex.Matches(value, @"^(子.*?)(\r|\n)",
System.Text.RegularExpressions.RegexOptions.Multiline);
foreach (System.Text.RegularExpressions.Match result in results)
{
//全体でのヒットした位置。ここでは改行も1文字または2文字とカウントします。
int index = result.Groups[1].Index;
//その位置までの改行。
var linebreaks = System.Text.RegularExpressions.Regex.Matches(value.Substring(0, index), @"(\r\n|\n)");
//その位置が何行目か。(行数はそこまでの改行の数+1)
int row = linebreaks.Count + 1;
System.Diagnostics.Debug.WriteLine($"ヒット:{result.Groups[1].Value} 開始位置:{index} {row}行目");
}
これを実行すると次の通りに出力されます。
ヒット:子曰學而時習之不亦説乎 開始位置:31 2行目
ヒット:子曰不患人之不己知 開始位置:44 3行目
メモ:正規表現の意味は次の通り。行頭(^)の直後に「子」があり、文字(.)が0個以上続き(*)、その後の最初の(?)改行(\rまたは\n)まで
メモ:正規表現に含まれる ( ) にマッチしたものは Groups[] で取得できます。Groups[0]は常に正規表現にマッチした全体を表し、Groups[1]は正規表現に含まれる 1つ目の ( ) 内にマッチしたものという意味になります。
末尾が「る。」で終わる行を検索する
string value = "論語の文章は「子曰」から始まるものが多い。例を挙げてみる。\r\n" +
"子曰學而時習之不亦説乎\r\n" +
"子曰不患人之不己知\r\n" +
"この「子曰」は「孔子はおっしゃった」という意味なので、\r\n" +
"孔子以外の人物の発言は次のように当然異なる書き出しとなる。\r\n" +
"子貢問曰貧而無諂富而無驕何如";
var results = System.Text.RegularExpressions.Regex.Matches(value, @"^(.*る。)(\r|\n)",
System.Text.RegularExpressions.RegexOptions.Multiline);
foreach (System.Text.RegularExpressions.Match result in results)
{
//全体でのヒットした位置。ここでは改行も1文字または2文字とカウントします。
int index = result.Groups[1].Index;
//その位置までの改行。
var linebreaks = System.Text.RegularExpressions.Regex.Matches(value.Substring(0, index), @"(\r\n|\n)");
//その位置が何行目か。(行数はそこまでの改行の数+1)
int row = linebreaks.Count + 1;
System.Diagnostics.Debug.WriteLine($"ヒット:{result.Groups[1].Value} 開始位置:{index} {row}行目");
}
これを実行すると次の通りに出力されます。
ヒット:論語の文章は「子曰」から始まるものが多い。例を挙げてみる。 開始位置:0 1行目
ヒット:孔子以外の人物の発言は次のように当然異なる書き出しとなる。 開始位置:84 5行目
メモ:正規表現の意味は次の通り。行頭(^)から文字(.)が0個以上続き(*)、その後に「る。」と改行(\rまたは\n)が連続する
メモ:正規表現に含まれる ( ) にマッチしたものは Groups[] で取得できます。Groups[0]は常に正規表現にマッチした全体を表し、Groups[1]は正規表現に含まれる 1つ目の ( ) 内にマッチしたものという意味になります。