DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

正規表現を使って文字列を検索し、抽出する

補足:ここでは正規表現の説明はしません。.NET Frameworkの正規表現の基本は、「正規表現の基本」で説明しています。
補足:「正規表現テストツール」を使って正規表現のテストを行うことができますので、お役立てください。

正規表現を使って文字列の検索し、検索された文字列を取得するには、RegexクラスとMatchメソッド(またはMatchsメソッド)を使用します。一致した要素はMatchオブジェクトとして返されます。

メールアドレスを抽出する

次の例ではTextBox1に入力された文字列からメールアドレスっぽい文字列をすべて検索し、表示します。ここで使用している正規表現パターンは、「Regular-Expressions.info」で紹介されているものです。

VB.NET
コードを隠すコードを選択
'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
C#
コードを隠すコードを選択
//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();
}

HTML内の<H>タグを抽出する

次にグループ化の例を示します。正規表現でグループ化を指定するには、「(?<(数字または名前)>)」のようにします。正規表現に一致したグループはMatchクラスのGroupsプロパティで取得できます。なおMSDNには、「HREFS のスキャン」という例や、「URL 情報の抽出」という例が紹介されています。

以下にTextBox1に入力された文字列を検索して、HTMLのHタグ(H1、H2、H3、...)とその部分のテキストを抽出する例を示します。先程の例ではMatchメソッドを使っていましたが、今回はMatchesメソッドを使ってみます。もちろん先ほどと同じようにMatchメソッドを使っても構いません。

VB.NET
コードを隠すコードを選択
'正規表現パターンとオプションを指定して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
C#
コードを隠すコードを選択
//正規表現パターンとオプションを指定して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);
}

HTML内のリンクを抽出する

下の例はTextBox1に入力された文字列を検索して、<a href="...">...</a>でリンクされているリンク先のURLとリンクされている文字列をすべて調べ、結果を出力するものです。今までの例ではインスタンスメソッドのMatches(あるいはMatch)を使用していましたが、今回は静的メソッドを使ってみます。

VB.NET
コードを隠すコードを選択
'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
C#
コードを隠すコードを選択
//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」という文字列を検索しています。

VB.NET
コードを隠すコードを選択
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
C#
コードを隠すコードを選択
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にはキャプチャされたすべての結果が入っています。

正規表現と一致するか調べる

正規表現を使って文字列がある形式と一致するか調べる」に移動しました。

  • 履歴:
  • 2009/5/18 全体的に書き換える。
  • 2009/6/20 「HTML内のリンクを抽出する」のコードが別のコードになっていたのを修正。
  • 2009/9/9 「HTML内のリンクを抽出する」の正規表現パターンを修正。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • .NET Tipsをご利用いただく際は、注意事項をお守りください。