補足:ここでは正規表現の説明はしません。.NET Frameworkの正規表現の基本は、「正規表現の基本」で説明しています。
補足:「正規表現テストツール」を使って正規表現のテストを行うことができますので、お役立てください。
正規表現を使って文字列の検索し、検索された文字列を取得するには、RegexクラスとMatchメソッド(またはMatchsメソッド)を使用します。一致した要素はMatchオブジェクトとして返されます。
次の例ではTextBox1に入力された文字列からメールアドレスっぽい文字列をすべて検索し、表示します。ここで使用している正規表現パターンは、「Regular-Expressions.info」で紹介されているものです。
'Regexオブジェクトを作成 Dim r As New System.Text.RegularExpressions.Regex( _ "\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b", _ System.Text.RegularExpressions.RegexOptions.IgnoreCase) 'TextBox1.Text内で正規表現と一致する対象を1つ検索 Dim m As System.Text.RegularExpressions.Match = r.Match(TextBox1.Text) '次のように一致する対象をすべて検索することもできる 'Dim mc As System.Text.RegularExpressions.MatchCollection = _ ' r.Matches(TextBox1.Text) While m.Success '一致した対象が見つかったときキャプチャした部分文字列を表示 Console.WriteLine(m.Value) '次に一致する対象を検索 m = m.NextMatch() End While
//Regexオブジェクトを作成 System.Text.RegularExpressions.Regex r = new System.Text.RegularExpressions.Regex( @"\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b", System.Text.RegularExpressions.RegexOptions.IgnoreCase); //TextBox1.Text内で正規表現と一致する対象を1つ検索 System.Text.RegularExpressions.Match m = r.Match(TextBox1.Text); //次のように一致する対象をすべて検索することもできる //System.Text.RegularExpressions.MatchCollection mc = r.Matches(TextBox1.Text); while (m.Success) { //一致した対象が見つかったときキャプチャした部分文字列を表示 Console.WriteLine(m.Value); //次に一致する対象を検索 m = m.NextMatch(); }
次にグループ化の例を示します。正規表現でグループ化を指定するには、「(?<(数字または名前)>)」のようにします。正規表現に一致したグループはMatchクラスのGroupsプロパティで取得できます。なおMSDNには、「HREFS のスキャン」という例や、「URL 情報の抽出」という例が紹介されています。
以下にTextBox1に入力された文字列を検索して、HTMLのHタグ(H1、H2、H3、...)とその部分のテキストを抽出する例を示します。先程の例ではMatchメソッドを使っていましたが、今回はMatchesメソッドを使ってみます。もちろん先ほどと同じようにMatchメソッドを使っても構いません。
'正規表現パターンとオプションを指定してRegexオブジェクトを作成 Dim r As New System.Text.RegularExpressions.Regex( _ "<(h[1-6])\b[^>]*>(.*?)</\1>", _ System.Text.RegularExpressions.RegexOptions.IgnoreCase Or _ System.Text.RegularExpressions.RegexOptions.Singleline) 'TextBox1.Text内で正規表現と一致する対象をすべて検索 Dim mc As System.Text.RegularExpressions.MatchCollection = _ r.Matches(TextBox1.Text) For Each m As System.Text.RegularExpressions.Match In mc '正規表現に一致したグループの文字列を表示 Console.WriteLine("タグ:" + m.Groups(1).Value + vbCrLf + _ "タグ内の文字列:" + m.Groups(2).Value) Next
//正規表現パターンとオプションを指定してRegexオブジェクトを作成 System.Text.RegularExpressions.Regex r = new System.Text.RegularExpressions.Regex( @"<(h[1-6])\b[^>]*>(.*?)</\1>", System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline); //TextBox1.Text内で正規表現と一致する対象をすべて検索 System.Text.RegularExpressions.MatchCollection mc = r.Matches(TextBox1.Text); foreach (System.Text.RegularExpressions.Match m in mc) { //正規表現に一致したグループと位置を表示 Console.WriteLine("タグ:" + m.Groups[1].Value + "\nタグ内の文字列:" + m.Groups[2].Value + "\nタグの位置:" + m.Groups[1].Index); }
下の例はTextBox1に入力された文字列を検索して、<a href="...">...</a>でリンクされているリンク先のURLとリンクされている文字列をすべて調べ、結果を出力するものです。今までの例ではインスタンスメソッドのMatches(あるいはMatch)を使用していましたが、今回は静的メソッドを使ってみます。
'TextBox1.Text内で正規表現と一致する対象をすべて検索 Dim mc As System.Text.RegularExpressions.MatchCollection = _ System.Text.RegularExpressions.Regex.Matches( _ TextBox1.Text, _ "<a\s+[^>]*href\s*=\s*(?:(?<quot>[""'])(?<url>.*?)\k<quot>|" + _ "(?<url>[^\s>]+))[^>]*>(?<text>.*?)</a>", _ System.Text.RegularExpressions.RegexOptions.IgnoreCase Or _ System.Text.RegularExpressions.RegexOptions.Singleline) For Each m As System.Text.RegularExpressions.Match In mc '正規表現に一致したグループを表示 Console.WriteLine("URL:{0}", m.Groups("url").Value) Console.WriteLine("テキスト:{0}", m.Groups("text").Value) Next
//TextBox1.Text内で正規表現と一致する対象をすべて検索 System.Text.RegularExpressions.MatchCollection mc = System.Text.RegularExpressions.Regex.Matches( TextBox1.Text, @"<a\s+[^>]*href\s*=\s*(?:(?<quot>[""'])(?<url>.*?)\k<quot>|" + @"(?<url>[^\s>]+))[^>]*>(?<text>.*?)</a>", System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline); foreach (System.Text.RegularExpressions.Match m in mc) { //正規表現に一致したグループを表示 Console.WriteLine("URL:{0}", m.Groups["url"].Value); Console.WriteLine("テキスト:{0}", m.Groups["text"].Value); }
同じ番号のグループに複数の箇所が一致する場合があります。例えば、「(\d)+」というパターンで「123」を検索すると、グループ1に「1」、「2」、「3」の3つの文字が一致します。また、.NET Frameworkではグループに名前や番号を付けることができますので、同じ名前や番号のグループを複数作ることもできます。このように同じ名前や番号のグループが複数あった場合どうなるかについて簡単に説明します。
このような場合、グループの値としては最後に一致したグループの値が入ります。しかし、キャプチャされたすべての値はグループのCapturesコレクションに格納されています。
具体的にどうなるか、例を示します。以下の例では、パターンを「(\d)+」とし、「123」という文字列を検索しています。
Dim r As New System.Text.RegularExpressions.Regex("(\d)+") Dim mc As System.Text.RegularExpressions.MatchCollection = r.Matches("123") For Each m As System.Text.RegularExpressions.Match In mc For i As Integer = 0 To m.Groups.Count - 1 Console.WriteLine("グループ{0}:{1}", i, m.Groups(i)) For l As Integer = 0 To m.Groups(i).Captures.Count - 1 Console.WriteLine(" キャプチャ{0}:{1}", l, m.Groups(i).Captures(l).Value) Next Next Next
System.Text.RegularExpressions.Regex r = new System.Text.RegularExpressions.Regex( @"(\d)+"); System.Text.RegularExpressions.MatchCollection mc = r.Matches("123"); foreach (System.Text.RegularExpressions.Match m in mc) { for (int i = 0; i < m.Groups.Count; i++) { Console.WriteLine("グループ{0}:{1}", i, m.Groups[i]); for (int l = 0; l < m.Groups[i].Captures.Count; l++) { Console.WriteLine(" キャプチャ{0}:{1}", l, m.Groups[i].Captures[l].Value); } } }
このプログラムを実行すると、以下のように表示されます。
グループ0:123 キャプチャ0:123 グループ1:3 キャプチャ0:1 キャプチャ1:2 キャプチャ2:3
この結果のように、グループ1には最後にキャプチャされた「3」が入りますが、グループ1のCapturesにはキャプチャされたすべての結果が入っています。
「正規表現を使って文字列がある形式と一致するか調べる」に移動しました。
注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。