Replaceメソッドはテキスト内で、正規表現パターンに一致した部分を全て置換する。以下に例を示す。これは最初に示した例で「2文字以上連続する空白文字」を「1個の空白文字」に置換するものだ。なお、Replaceメソッドにも静的メソッドがあるが、ここでは省略する。
var text = "regular expression is so great!";
var pattern = @"\s\s+";
var regex = new Regex(pattern);
var result = regex.Replace(text, " ");
Replaceメソッドの典型的な使い方は上に示した通りだが、正規表現中で指定されたグループの値(キャプチャー)を参照することも可能だ。全く意味がない例だが、上のコードは例えば次のように書き換えられる。
var text = "regular expression is so great!";
var pattern = @"(\s)\s+";
var regex = new Regex(pattern);
var result = regex.Replace(text, "$1");
このコードでは、「(\s)」のようにかっこで「\s」を囲んでいる。このかっこのことを「グループ化構成体」と呼ぶ。グループ化構成体は、正規表現の中の一部(部分式)のことであり、マッチした場合にはかっこで囲まれた範囲がキャプチャーされ、後から利用できるようになる。上の例では「$1」として置換パターンから参照しているが、正規表現内から参照することも可能だ(これについては後述する)。
上のコードでは「\s\s+」の最初の「\s」をかっこで囲んでいるので、「2文字以上連続する空白文字」の「最初の空白文字」がグループを形成し、テキスト(regular expression is so great!)が正規表現パターンにマッチした場合、その「最初の空白文字」(この場合は「regular」直後の空白文字)がキャプチャー(後から利用できるように保存)され、「1」という番号が付けられる。そのため、Replaceメソッドでは「$1」のようにして「$」にこのキャプチャーの番号である「1」を付加することで「最初の空白文字」を置換文字列として指定している。なお、これはあくまでも例であり、意味はない。実際上は、より適切な使い方があるので、本特集を通して、そうした例を見ていくことにしよう。
また、正規表現中からグループを参照する際には、「$」ではなく「\」に番号を付けて参照する(これを「前方参照構成体」という)。以下に例を示す。
var text = "<h1>some text</h1>";
var regex = new Regex(@"<(h1)>.*</\1>");
var m = regex.Match(text);
Console.WriteLine(m);
上のコードでは正規表現パターンを「<(h1)>.*</\1>」のようにしている。この「\1」が前方参照構成体だ。見れば分かるように、「h1」をかっこで囲み、「</\1>」とすることでh1要素の閉じタグである「</h1>」を表現している。これだけだとあまり役には立たなさそうだが「<(h[1-6])>」とすれば任意の見出しタグを表現できる。例えば、上のコードを次のようにしてみよう。
var text = @"<h1>heading text</h1>
<div>some texts continues....</div>
<h2>yet another text</h2>";
var regex = new Regex(@"<(h[1-6])>.*</\1>");
var matches = regex.Matches(text);
foreach (Match m in matches)
{
Console.WriteLine(m);
}
このようにすると、<div>要素にはマッチさせることなく、<h1>要素と<h2>要素だけを抽出できる。
<h1>heading text</h1>
<h2>yet another text</h2>
大量のテキストから見出し要素だけを抜き出してチェックをしたいという場合に役に立つことが想像できるだろう。このように正規表現を記述する中で、「前に書いたパターンをここでも使いたい」といったときに役立つのがグループとキャプチャーだ。
また、グループには名前を付けることも可能だ。これには「(?<グループ名>…… 正規表現 ……)」というグループ化構成体を使ってグループに名前を付けて、「\k<グループ名>」という形式の前方参照構成体を使用してその値を参照する。以下に例を示す。
var text = @"<h1>heading text</h1>
<div>some texts continues....</div>
<h2>yet another text</h2>";
var regex = new Regex(@"<(?<headingtag>h[1-6])>.*</\k<headingtag>>");
var matches = regex.Matches(text);
foreach (Match m in matches)
{
Console.WriteLine(m);
}
ここではグループに「headingtag」という名前を付けている。このグループにキャプチャーされた値は「\k<headingtag>」として参照できる。
キャプチャーやグループに関する情報はMatchesオブジェクトのCapturesプロパティやGroupsプロパティに保存されるので、これをプログラムから参照することも可能だ。以下に例を示す(説明は省略する)。
var text = @"<h1>heading text</h1>
<div>some texts continues....</div>
<h2>yet another text</h2>";
var regex = new Regex(@"<(?<headingtag>h[1-6])>.*</\k<headingtag>>");
var matches = regex.Matches(text);
string resulttext = "";
foreach (Match m in matches)
{
resulttext += $"Match: {m}\n";
foreach (Group g in m.Groups)
{
resulttext += $" Group: {g}\n";
foreach (var item in g.Captures)
{
resulttext += $" Capture: {item}\n";
}
}
}
Console.WriteLine(resulttext);
なお、Replaceメソッドの詳しい使い方については「.NET TIPS:正規表現を使って文字列を置換するには?」を参照されたい。また、Regexクラスでは、正規表現を使って文字列を分割するためのSplitメソッドもある。これについては「.NET TIPS:正規表現を使って文字列を分割するには?」を参照されたい。
今回の最後に、ここまでに出てきた正規表現の用語やメタ文字などを一覧しておこう。
本稿ではRegexクラスのIsMatch/Match/Matches/Replaceの各メソッドの基本的な使い方を見ながら、正規表現のさまざまな要素を紹介してきた。ここでは以下のような用語やメタ文字などを覚えておこう。
要素 | 説明 |
---|---|
\s | 空白文字を表すメタ文字(あるいは空白を表す文字クラスの省略表記) |
+ | 直前の文字の1文字以上の繰り返し |
[……] | 文字クラス。[]内に指定された文字の中のいずれかにマッチする |
| | 「|」で区切られた要素のいずれかにマッチする |
(……) | グループ化構成体。かっこで囲まれた範囲に記述された正規表現にマッチする文字列をキャプチャーする |
\番号 | 名前のないグループにキャプチャーされた内容を「番号」で参照する |
(?<……>) | グループ化構成体(名前付き)。かっこで囲まれた範囲に記述された正規表現にマッチする文字列を名前付きグループにキャプチャーする |
\k<グループ名> | 名前付きグループにキャプチャーされた内容を「グループ名」で参照する |
$ | 名前のないグループにキャプチャーされた内容を置換パターンから「番号」で参照する(本稿では登場しなかったが「${グループ名}」として名前付きグループにキャプチャーされた内容も参照可能) |
IsMatchメソッド | テキストが正規表現パターンにマッチするかどうかを判定する |
Matchメソッド | テキストで正規表現パターンに最初にマッチした部分に関する情報を含んだMatchオブジェクトを返送する。次のマッチはNextMatchメソッドで検索できる |
Matchesメソッド | テキスト内で正規表現パターンにマッチした全ての部分についての情報を含んだMatchCollectionオブジェクトを返送する |
Replaceメソッド | テキスト内で正規表現にマッチした部分を、置換パターンで置換する |
本稿で取り上げた要素 |
今回はチートシートというよりも、C#で正規表現を取り扱うための基本の説明になってしまったが、次回以降ではC#で使用する正規表現についてより詳しく取り上げていくことにしよう。
Copyright© Digital Advantage Corp. All Rights Reserved.