C#正規表現:Regexクラスとパターンマッチング実践ガイド
正規表現(Regular Expression)とは、入力テキストに対してマッチングできるパターンのことです。.NET Frameworkには正規表現エンジンが用意されており、このようなマッチングを実行できます。パターンは1つ以上の文字リテラル、演算子、または構成要素で構成されます。
正規表現を定義するための構成要素
正規表現を定義するための文字、演算子、構成要素にはさまざまなカテゴリがあります。
- 文字エスケープ
- 文字クラス
- アンカー
- グループ化構成要素
- 量指定子
- 後方参照構成要素
- 選択構成要素
- 置換
- その他の構成要素
Regexクラス
Regexクラスは正規表現を表現するために使用されます。よく使用されるメソッドは以下の通りです。
| No. | メソッドと説明 |
|---|---|
| 1 | IsMatch(input) - 指定入力文字列で正規表現が一致するか判定 |
| 2 | IsMatch(input, startat) - 指定位置から検索開始 |
| 3 | IsMatch(input, pattern) - 静的メソッドでパターン指定して判定 |
| 4 | Matches(input) - 入力文字列で正規表現のすべての出現を検索しMatchCollectionを返す |
| 5 | Replace(input, replacement) - 一致する部分を置換文字列で置き換え |
| 6 | Split(input) - 正規表現パターンで入力文字列を分割し配列を返す |
よく使用される正規表現パターン
| パターン | 意味 | 例 |
|---|---|---|
. | 改行以外の任意の1文字 | a.c → "abc", "axc" |
\d | 数字(0-9) | \d{3} → "123" |
\D | 数字以外 | |
\w | 単語文字(英数字と_) | \w+ → "hello123" |
\W | 非単語文字 | |
\s | 空白文字(スペース、タブ、改行) | |
\S | 非空白文字 | |
^ | 行の先頭(アンカー) | ^Hello |
$ | 行の末尾(アンカー) | World$ |
* | 0回以上の繰り返し | ab*c → "ac", "abc", "abbc" |
+ | 1回以上の繰り返し | ab+c → "abc", "abbc" |
? | 0回または1回 | ab?c → "ac", "abc" |
{n} | ちょうどn回 | \d{3} |
{n,} | n回以上 | \d{2,} |
{n,m} | n回以上m回以下 | \d{2,4} |
[abc] | a, b, cのいずれか1文字 | [aeiou] |
[^abc] | a, b, c以外の1文字 | |
[a-z] | aからzの範囲 | |
(pattern) | キャプチャグループ | (\d{3})-(\d{4}) |
(?:pattern) | 非キャプチャグループ | |
| | または(選択) | cat|dog |
実用例
例1:'S'で始まる単語をマッチング
using System;
using System.Text.RegularExpressions;
namespace RegExApplication {
class Program {
private static void ShowMatch(string text, string expr) {
Console.WriteLine("The Expression: " + expr);
MatchCollection mc = Regex.Matches(text, expr);
foreach (Match m in mc) {
Console.WriteLine(m);
}
}
static void Main(string[] args) {
string str = "A Thousand Splendid Suns";
Console.WriteLine("Matching words that start with 'S': ");
ShowMatch(str, @"\bS\S*");
Console.ReadKey();
}
}
}
実行結果:
Matching words that start with 'S':
The Expression: \bS\S*
Splendid
Suns
例2:'m'で始まり'e'で終わる単語をマッチング
string str = "make maze and manage to measure it";
Console.WriteLine("Matching words start with 'm' and ends with 'e':");
ShowMatch(str, @"\bm\S*e\b");
実行結果:
Matching words start with 'm' and ends with 'e':
The Expression: \bm\S*e\b
make
maze
manage
measure
例3:余分な空白の置換
using System;
using System.Text.RegularExpressions;
namespace RegExApplication {
class Program {
static void Main(string[] args) {
string input = "Hello World ";
string pattern = @"\s+";
string replacement = " ";
Regex rgx = new Regex(pattern);
string result = rgx.Replace(input, replacement);
Console.WriteLine("Original String: '{0}'", input);
Console.WriteLine("Replacement String: '{0}'", result);
Console.ReadKey();
}
}
}
実行結果:
Original String: 'Hello World '
Replacement String: 'Hello World '
実用的なパターン例
メールアドレス検証(簡易版)
string emailPattern = @"^[^@\s]+@[^@\s]+\.[^@\s]+$";
bool isValid = Regex.IsMatch("user@example.com", emailPattern); // true
電話番号抽出
string text = "電話: 03-1234-5678, 携帯: 090-1234-5678";
foreach (Match m in Regex.Matches(text, @"\d{2,4}-\d{4}-\d{4}")) {
Console.WriteLine(m.Value);
}
// 03-1234-5678
// 090-1234-5678
HTMLタグ除去
string html = "Hello World!
";
string plain = Regex.Replace(html, @"<[^>]+>", "");
// "Hello World!"
キャプチャグループを使用した日付解析
string dateText = "2024-03-15";
var match = Regex.Match(dateText, @"(?\d{4})-(?\d{2})-(?\d{2})");
if (match.Success) {
Console.WriteLine($"Year: {match.Groups["year"].Value}");
Console.WriteLine($"Month: {match.Groups["month"].Value}");
Console.WriteLine($"Day: {match.Groups["day"].Value}");
}
RegexOptions
| オプション | 説明 |
|---|---|
IgnoreCase | 大文字小文字を区別しない |
Multiline | ^/$を行頭/行末として扱う |
Singleline | .を改行にもマッチさせる |
Compiled | アセンブリにコンパイル(初回遅いが実行高速) |
ExplicitCapture | 明示的グループのみキャプチャ |
CultureInvariant | カルチャ非依存の比較 |
オプション指定例
// 大文字小文字無視
Regex regex = new Regex(@"pattern", RegexOptions.IgnoreCase);
// 複数オプション組み合わせ
Regex regex2 = new Regex(@"^start.*end$", RegexOptions.Multiline | RegexOptions.IgnoreCase);
// 静的メソッドでオプション指定
bool matched = Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase);
パフォーマンスのヒント
- 同じパターンを繰り返し使用する場合は
Regexインスタンスを再利用する(またはCompiledオプション) - 過度なバックトラックを引き起こすパターン(
(.*)*等)を避ける - 単純な文字列検索/置換には
string.Contains/Replaceの方が高速 Regex.Matchで最初の1つだけ必要な場合はMatchesを使わない
よくある落とし穴
@プレフィックス(逐語的文字列リテラル)を忘れるとバックスラッシュが二重エスケープ必要になる- 貪欲マッチ(
.*)が意図せず長くマッチする → 非貪欲(.*?)を使用 ^/$はデフォルトで文字列全体の先頭/末尾。複数行モードではMultilineオプション必須
C言語
- C# の式、文、ブロック:実践例で徹底理解
- C# 文字列をマスターする:基礎、操作、高度なテクニック
- C++文字列関数をマスター:strcpy、strcat、strlen、strcmpの実践例
- C 言語の文字列をマスター: 宣言、入力、出力、ライブラリ関数
- Python str.count()マスター:文字と部分文字列のカウント実例集
- Javaの式、文、ブロックを理解する
- Java文字列をマスター:生成、メソッド、ベストプラクティス
- Java Enumの文字列表現マスター:デフォルト、オーバーライド、高度なパターン
- Javaラムダ式完全ガイド:基礎からStream APIまで
- Java Stringクラス完全ガイド:生成、操作、主要メソッド46選
- Java正規表現: java.util.regexでパターンマッチングをマスターする