C# RegexOptionsとは?正規表現オプションの使い方・一覧・組み合わせを実例で徹底解説

はじめに

C#で正規表現を使うとき、単にパターンを書くだけではなく、「大文字・小文字を区別しない」「複数行として扱う」「改行を含めてマッチさせる」「高速化する」といった動作を指定できます。そのために使うのがRegexOptionsです。

RegexOptionsは、System.Text.RegularExpressions名前空間で提供される列挙型で、RegexクラスやRegex.MatchRegex.IsMatchRegex.Matchesなどのメソッドに渡して正規表現エンジンの動作を変更します。Microsoft公式ドキュメントでも、RegexOptionsは正規表現オプションを設定するための列挙値であり、ビット単位の組み合わせをサポートする列挙型として定義されています。Microsoft Learn

この記事では、C#のRegexOptionsについて、基本的な使い方、各オプションの意味、組み合わせ方法、実務でよく使うサンプル、パフォーマンスや安全性の注意点まで詳しく解説します。

1. C# RegexOptionsとは?正規表現の動作を変えるオプション

1-1. RegexOptionsの役割と使う場面

RegexOptionsは、C#の正規表現処理において「マッチのルール」を変更するための設定です。

たとえば、通常の正規表現ではabcというパターンはabcには一致しますが、ABCには一致しません。しかし、RegexOptions.IgnoreCaseを指定すると、大文字・小文字を区別せずに一致判定できます。

C#
using System.Text.RegularExpressions;

string text = "Hello C# RegexOptions";
bool result = Regex.IsMatch(text, "hello", RegexOptions.IgnoreCase);

Console.WriteLine(result); // True

このように、正規表現パターンそのものを複雑にせず、検索や検証の動作をオプションとして切り替えられるのがRegexOptionsの役割です。

1-2. RegexOptionsを指定しない場合のデフォルト動作

RegexOptionsを指定しない場合、C#の正規表現は基本的にRegexOptions.Noneと同じ動作になります。

デフォルトでは、主に次のように動作します。

項目デフォルト動作
大文字・小文字区別する
.改行文字には一致しない
^ / $入力文字列全体の先頭・末尾を基準にする
パターン内の空白通常の文字として扱う
キャプチャ名前なしの丸括弧もキャプチャする
検索方向左から右

Microsoftの正規表現オプションの説明でも、既定では大文字・小文字を区別し、パターン内の空白はリテラル空白として解釈され、キャプチャグループは暗黙的にも明示的にも名前付けされると説明されています。Microsoft Learn

C#
string text = "ABC";
Console.WriteLine(Regex.IsMatch(text, "abc")); // False

RegexOptionsを指定しないと、abcABCは別の文字列として扱われます。

1-3. RegexOptionsを使うメリット

RegexOptionsを使うメリットは、正規表現の可読性・保守性・安全性・性能を調整できることです。

たとえば、大文字・小文字を無視したい場合に、パターンを[aA][bB][cC]のように書くよりも、RegexOptions.IgnoreCaseを指定したほうが簡潔です。

C#
Regex.IsMatch("ABC", "abc", RegexOptions.IgnoreCase);

また、複数行ログを処理する場合はRegexOptions.Multiline、改行を含むHTML風テキストを処理する場合はRegexOptions.Singleline、繰り返し使う正規表現を高速化したい場合はRegexOptions.Compiledを検討できます。

つまりRegexOptionsは、正規表現パターンだけでは表現しづらい「処理方針」をコード上で明確にするための仕組みです。

1-4. Regexクラス・Regex.Match・Regex.IsMatchでの指定方法

RegexOptionsは、主に次のような場所で指定できます。

C#
// Regexインスタンスを作成するとき
var regex = new Regex("abc", RegexOptions.IgnoreCase);

// 静的メソッド Regex.IsMatch で指定
bool isMatch = Regex.IsMatch("ABC", "abc", RegexOptions.IgnoreCase);

// 静的メソッド Regex.Match で指定
Match match = Regex.Match("ABC", "abc", RegexOptions.IgnoreCase);

// 静的メソッド Regex.Matches で指定
MatchCollection matches = Regex.Matches("ABC abc", "abc", RegexOptions.IgnoreCase);

Regex.Matchには、正規表現オプションやタイムアウトを指定できるオーバーロードも用意されています。Microsoft Learn

2. RegexOptionsの基本的な使い方

2-1. RegexOptionsを1つだけ指定する書き方

RegexOptionsを1つだけ指定する場合は、メソッドやコンストラクターの引数にそのまま渡します。

C#
using System.Text.RegularExpressions;

string text = "CSharp";
string pattern = "csharp";

bool result = Regex.IsMatch(text, pattern, RegexOptions.IgnoreCase);

Console.WriteLine(result); // True

この例では、RegexOptions.IgnoreCaseによって大文字・小文字を区別しない検索になります。

2-2. 複数のRegexOptionsを組み合わせる書き方

RegexOptionsFlags属性を持つ列挙型なので、複数の値を組み合わせて指定できます。

たとえば、大文字・小文字を無視しつつ、複数行モードで検索したい場合は次のように書きます。

C#
RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Multiline;

bool result = Regex.IsMatch(text, pattern, options);

RegexOptionsはビット単位の組み合わせをサポートする列挙型です。Microsoft Learn

2-3. ビット演算子「|」でオプションを結合する方法

複数のRegexOptionsを結合するときは、ビットOR演算子の|を使います。

C#
var options = RegexOptions.IgnoreCase
| RegexOptions.Multiline
| RegexOptions.CultureInvariant;

これは「IgnoreCaseも有効、Multilineも有効、CultureInvariantも有効」という意味です。

反対に、&&+で結合するものではありません。

C#
// 推奨されない書き方
// RegexOptions.IgnoreCase + RegexOptions.Multiline

// 正しい書き方
RegexOptions.IgnoreCase | RegexOptions.Multiline

2-4. インラインオプションとの違い

C#の正規表現では、RegexOptionsの代わりにパターン内でインラインオプションを指定することもできます。

C#
bool result = Regex.IsMatch("ABC", "(?i)abc");

(?i)は大文字・小文字を無視するインラインオプションです。RegexOptions.IgnoreCaseと似た効果があります。

C#
bool result = Regex.IsMatch("ABC", "abc", RegexOptions.IgnoreCase);

ただし、すべてのRegexOptionsがインラインで指定できるわけではありません。たとえば、RegexOptions.Compiledはコード側で指定するオプションであり、インラインオプションとしては指定できません。Microsoftのドキュメントでも、CompiledRegexコンストラクターや静的メソッドのoptions引数で指定するもので、インラインオプションとしては利用できないと説明されています。Microsoft Learn

2-5. よく使う基本コード例

実務でよく使う基本形は次のようなコードです。

C#
using System;
using System.Text.RegularExpressions;

class Program
{
static void Main()
{
string text = """
ERROR: File not found
info: retrying
ERROR: Access denied
""";

string pattern = "^error:";

var options = RegexOptions.IgnoreCase | RegexOptions.Multiline;

foreach (Match match in Regex.Matches(text, pattern, options))
{
Console.WriteLine(match.Value);
}
}
}

この例では、RegexOptions.IgnoreCaseERRORerrorを同一視し、RegexOptions.Multilineで各行の先頭に対して^を評価しています。

3. RegexOptions一覧と各オプションの意味

3-1. RegexOptions.None:オプションなし

RegexOptions.Noneは、特別なオプションを指定しない状態を表します。

C#
bool result = Regex.IsMatch("ABC", "abc", RegexOptions.None);
Console.WriteLine(result); // False

RegexOptions.Noneは、明示的に「オプションなし」と書きたい場合に使います。通常はRegexOptions引数を省略した場合と同じような意味になります。

C#
Regex.IsMatch("ABC", "abc");
Regex.IsMatch("ABC", "abc", RegexOptions.None);

可読性を高める目的で、変数に代入しておくケースもあります。

C#
RegexOptions options = RegexOptions.None;

3-2. RegexOptions.IgnoreCase:大文字・小文字を区別しない

RegexOptions.IgnoreCaseは、大文字・小文字を区別せずにマッチさせるオプションです。公式ドキュメントでも、IgnoreCaseは大文字・小文字を区別しない一致を指定する値として定義されています。Microsoft Learn

C#
string text = "RegexOptions";
bool result = Regex.IsMatch(text, "regexoptions", RegexOptions.IgnoreCase);

Console.WriteLine(result); // True

検索キーワード、メールアドレス、拡張子、ログレベルなど、大文字・小文字の違いを無視したい場面でよく使います。

C#
string fileName = "Report.PDF";
bool isPdf = Regex.IsMatch(fileName, @"\.pdf$", RegexOptions.IgnoreCase);

Console.WriteLine(isPdf); // True

3-3. RegexOptions.Multiline:複数行モード

RegexOptions.Multilineは、^$の意味を変えるオプションです。

通常、^は文字列全体の先頭、$は文字列全体の末尾付近を表します。しかしMultilineを指定すると、^$が各行の先頭・末尾にも一致するようになります。

C#
string text = """
INFO start
ERROR failed
INFO end
""";

string pattern = "^ERROR";

bool result = Regex.IsMatch(text, pattern, RegexOptions.Multiline);

Console.WriteLine(result); // True

ログファイル、CSV、設定ファイルなど、行単位で判定したいときに便利です。

3-4. RegexOptions.Singleline:ドットで改行も対象にする

RegexOptions.Singlelineは、.の意味を変えるオプションです。

通常、.は改行文字\n以外の任意の1文字に一致します。Singlelineを指定すると、.が改行を含むすべての文字に一致します。MicrosoftのRegexOptions列挙型の説明でも、Singlelineはドットの意味を変更し、すべての文字に一致するようにすると説明されています。Microsoft Learn

C#
string text = """
<div>
Hello
</div>
""";

string pattern = "<div>.*</div>";

bool result1 = Regex.IsMatch(text, pattern);
bool result2 = Regex.IsMatch(text, pattern, RegexOptions.Singleline);

Console.WriteLine(result1); // False
Console.WriteLine(result2); // True

複数行のHTML風テキスト、XML風テキスト、テンプレート文字列などから範囲を取り出すときに使われます。

3-5. RegexOptions.Compiled:正規表現をコンパイルして高速化する

RegexOptions.Compiledは、正規表現を内部的にコンパイルして実行時性能を高めるためのオプションです。

C#
var regex = new Regex(@"\d{4}-\d{2}-\d{2}", RegexOptions.Compiled);

bool result = regex.IsMatch("2026-06-18");
Console.WriteLine(result); // True

Microsoftのドキュメントでは、RegexOptions.Compiledを指定したRegexオブジェクトは、正規表現を高レベルの内部命令ではなくCILコードにコンパイルし、JITコンパイラーがネイティブコードに変換できるため、マッチ処理のコストが小さくなる可能性がある一方、Regexオブジェクトの構築コストは高くなると説明されています。Microsoft Learn

つまり、Compiledは「何度も使う正規表現」には向いていますが、「1回だけ使う正規表現」では初期化コストのほうが目立つ場合があります。

3-6. RegexOptions.CultureInvariant:カルチャに依存しない比較

RegexOptions.CultureInvariantは、言語や地域設定に依存しない比較を行うためのオプションです。

C#
var options = RegexOptions.IgnoreCase | RegexOptions.CultureInvariant;

bool result = Regex.IsMatch("FILE.TXT", @"\.txt$", options);

Console.WriteLine(result); // True

大文字・小文字の扱いは、カルチャによって微妙に異なる場合があります。特に、サーバー環境、ユーザーのロケール、OS設定などに影響されたくない処理では、CultureInvariantを組み合わせることで判定のブレを抑えられます。

ファイル拡張子、プロトコル名、識別子、ログレベルなど、自然言語ではなく機械的な文字列を扱う場合に使いやすいオプションです。

3-7. RegexOptions.IgnorePatternWhitespace:空白やコメントを無視する

RegexOptions.IgnorePatternWhitespaceは、正規表現パターン内のエスケープされていない空白を無視し、#から始まるコメントを書けるようにするオプションです。Microsoftの説明でも、このオプションはパターンからエスケープされていない空白を削除し、#でマークされたコメントを有効にするとされています。Microsoft Learn

複雑な正規表現を読みやすく書きたいときに便利です。

C#
string pattern = @"
^ # 行頭
[A-Z0-9._%+-]+ # ローカル部
@
[A-Z0-9.-]+ # ドメイン
\.
[A-Z]{2,} # TLD
$ # 行末
";

var options = RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace;

bool result = Regex.IsMatch("user@example.com", pattern, options);

Console.WriteLine(result); // True

複雑な入力チェックや抽出パターンでは、コメント付きで正規表現を書けるため、保守性が大きく上がります。

3-8. RegexOptions.ExplicitCapture:名前付き・番号付きキャプチャを制御する

RegexOptions.ExplicitCaptureは、明示的に名前付きまたは番号付きとして指定されたグループだけをキャプチャするオプションです。

通常、丸括弧(...)はグループ化と同時にキャプチャも行います。

C#
Match match = Regex.Match("abc123", @"([a-z]+)(\d+)");
Console.WriteLine(match.Groups[1].Value); // abc
Console.WriteLine(match.Groups[2].Value); // 123

ExplicitCaptureを指定すると、通常の(...)はキャプチャ対象ではなくなります。

C#
Match match = Regex.Match(
"abc123",
@"([a-z]+)(?<number>\d+)",
RegexOptions.ExplicitCapture
);

Console.WriteLine(match.Groups["number"].Value); // 123

Microsoftの説明でも、ExplicitCaptureは明示的な名前付きグループまたは番号付きグループだけを有効なキャプチャとし、名前のない括弧を非キャプチャグループのように扱えるとされています。Microsoft Learn

3-9. RegexOptions.RightToLeft:右から左へ検索する

RegexOptions.RightToLeftは、通常の左から右ではなく、右から左へ検索するオプションです。

C#
string text = "id=100; id=200; id=300";
string pattern = @"id=\d+";

Match match = Regex.Match(text, pattern, RegexOptions.RightToLeft);

Console.WriteLine(match.Value); // id=300

末尾に近い一致を探したい場合や、最後に出現するパターンを取得したい場合に便利です。

ただし、パターンそのものを右から読むというより、「検索方向が右から左になる」と考えると理解しやすいです。先読み・後読みなどの扱いには注意が必要です。

3-10. RegexOptions.ECMAScript:ECMAScript互換の動作にする

RegexOptions.ECMAScriptは、ECMAScript互換の正規表現動作を有効にするオプションです。

C#
var options = RegexOptions.ECMAScript | RegexOptions.IgnoreCase;

bool result = Regex.IsMatch("abc", @"\w+", options);

Console.WriteLine(result); // True

注意点として、RegexOptions.ECMAScriptは組み合わせられるオプションが制限されています。公式ドキュメントでは、ECMAScriptIgnoreCaseMultilineCompiledとのみ組み合わせ可能で、それ以外の値と一緒に使うと例外が発生すると説明されています。Microsoft Learn

C#
// 例外になる可能性がある組み合わせ
var options = RegexOptions.ECMAScript | RegexOptions.Singleline;

JavaScript風の正規表現動作に寄せたい場合を除き、通常のC#開発では頻繁に使うオプションではありません。

3-11. RegexOptions.NonBacktracking:バックトラッキングを抑えて安全にマッチする

RegexOptions.NonBacktrackingは、バックトラッキングを避け、入力長に対して線形時間で処理できる方式を使うオプションです。MicrosoftのRegexOptions列挙型の説明でも、NonBacktrackingはバックトラッキングを回避し、入力の長さに対する線形時間処理を保証するアプローチを使うと説明されています。Microsoft Learn

C#
var regex = new Regex(
@"^[a-z0-9_-]{3,20}$",
RegexOptions.IgnoreCase | RegexOptions.NonBacktracking
);

bool result = regex.IsMatch("user_123");

Console.WriteLine(result); // True

バックトラッキングを多用するパターンは、入力によって極端に遅くなることがあります。NonBacktrackingは、そのようなリスクを減らしたい場合に役立ちます。

ただし、後方参照や一部の高度な構文など、バックトラッキングに依存する機能が使えない場合があります。万能ではないため、対象パターンで使えるか確認しながら導入することが重要です。

なお、.NET 10のドキュメントではRegexOptions.AnyNewLineも列挙値として掲載されています。これは、^$\Z.\nだけではなく、\r\nやUnicode改行など一般的な改行シーケンスを認識するためのオプションです。Microsoft Learn

4. よく使うRegexOptionsの実例

4-1. IgnoreCaseでメールアドレスやキーワードを大小文字無視で検索する

メールアドレスやキーワード検索では、大文字・小文字を区別したくない場面が多くあります。

C#
string text = "Contact: USER@EXAMPLE.COM";
string pattern = @"[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}";

Match match = Regex.Match(text, pattern, RegexOptions.IgnoreCase);

Console.WriteLine(match.Value); // USER@EXAMPLE.COM

キーワード検索でも同様です。

C#
string body = "C# RegexOptions is useful.";
bool contains = Regex.IsMatch(body, "regexoptions", RegexOptions.IgnoreCase);

Console.WriteLine(contains); // True

IgnoreCaseを使えば、検索語をすべて小文字・大文字に変換する前処理を減らせます。

4-2. Multilineで行頭・行末を行単位で判定する

ログファイルからERRORで始まる行を抽出する場合、RegexOptions.Multilineが便利です。

C#
string log = """
INFO Application started
ERROR File not found
WARN Retry
ERROR Access denied
""";

string pattern = "^ERROR.*$";

foreach (Match match in Regex.Matches(log, pattern, RegexOptions.Multiline))
{
Console.WriteLine(match.Value);
}

出力結果は次のようになります。

ERROR File not found
ERROR Access denied

^$を行単位で使えるため、ログ解析や設定ファイルの処理に向いています。

4-3. Singlelineで複数行テキスト全体を対象にする

Singlelineは、.で改行を含めてマッチさせたいときに使います。

C#
string html = """
<section>
<h1>Title</h1>
<p>Hello</p>
</section>
""";

string pattern = "<section>.*?</section>";

Match match = Regex.Match(html, pattern, RegexOptions.Singleline);

Console.WriteLine(match.Success); // True

.*?のような最短一致と組み合わせると、複数行ブロックの抽出に使いやすくなります。

ただし、HTMLやXMLを本格的に解析する場合は、正規表現ではなく専用パーサーを使うほうが安全です。正規表現は、構造が単純で入力形式が限定されている場合に使うのが基本です。

4-4. IgnorePatternWhitespaceで読みやすい正規表現を書く

複雑なパターンは、1行で書くと読みづらくなります。

C#
string pattern = @"^\d{4}-\d{2}-\d{2}$";

IgnorePatternWhitespaceを使うと、次のようにコメント付きで書けます。

C#
string pattern = @"
^ # 文字列の先頭
\d{4} # 年
-
\d{2} # 月
-
\d{2} # 日
$ # 文字列の末尾
";

bool result = Regex.IsMatch(
"2026-06-18",
pattern,
RegexOptions.IgnorePatternWhitespace
);

Console.WriteLine(result); // True

チーム開発では、正規表現の意図をコメントとして残せるため、レビューや保守がしやすくなります。

4-5. Compiledで繰り返し使う正規表現を高速化する

同じ正規表現を大量に繰り返し使う場合は、RegexOptions.Compiledを検討できます。

C#
var dateRegex = new Regex(
@"^\d{4}-\d{2}-\d{2}$",
RegexOptions.Compiled
);

string[] values = { "2026-06-18", "2026/06/18", "2026-12-01" };

foreach (string value in values)
{
Console.WriteLine(dateRegex.IsMatch(value));
}

Compiledは、作成コストが高くなる代わりに、繰り返しマッチする処理では性能向上が期待できます。Microsoftのドキュメントでも、Compiledは構築コストが高くなる一方、マッチ処理コストは小さくなる可能性があると説明されています。Microsoft Learn

4-6. CultureInvariantで環境差による判定ブレを防ぐ

サーバーやユーザー環境によってカルチャが異なる場合、文字の大小比較で予期しない差が出ることがあります。

C#
var options = RegexOptions.IgnoreCase | RegexOptions.CultureInvariant;

bool result = Regex.IsMatch(
"Content-Type: TEXT/HTML",
@"content-type:\s*text/html",
options
);

Console.WriteLine(result); // True

HTTPヘッダー、ファイル拡張子、識別子、設定キーなど、自然言語ではない文字列の比較では、CultureInvariantを組み合わせると安定した判定をしやすくなります。

4-7. RightToLeftで末尾側から最初に一致する文字列を探す

文字列の最後に出てくるパターンだけを取得したい場合は、RightToLeftが使えます。

C#
string path = "/users/docs/report-final.pdf";
string pattern = @"[^/]+$";

Match match = Regex.Match(path, pattern, RegexOptions.RightToLeft);

Console.WriteLine(match.Value); // report-final.pdf

また、同じ形式のIDが複数ある文字列から最後のIDを取り出す場合にも使えます。

C#
string text = "id=100, id=200, id=300";
Match match = Regex.Match(text, @"id=\d+", RegexOptions.RightToLeft);

Console.WriteLine(match.Value); // id=300

5. RegexOptionsの組み合わせパターン

5-1. IgnoreCase + Multilineの使い方

IgnoreCase + Multilineは、ログや設定ファイルの行単位検索でよく使う組み合わせです。

C#
string log = """
info: start
ERROR: failed
error: retry failed
""";

var options = RegexOptions.IgnoreCase | RegexOptions.Multiline;

foreach (Match match in Regex.Matches(log, "^error:.*$", options))
{
Console.WriteLine(match.Value);
}

ERRORerrorErrorなどを区別せず、各行の先頭から検索できます。

5-2. Singleline + IgnoreCaseの使い方

Singleline + IgnoreCaseは、複数行のブロックを大文字・小文字を無視して抽出したい場合に便利です。

C#
string text = """
<ARTICLE>
Hello
</ARTICLE>
""";

var options = RegexOptions.Singleline | RegexOptions.IgnoreCase;

Match match = Regex.Match(text, "<article>.*?</article>", options);

Console.WriteLine(match.Success); // True

タグ名の大文字・小文字が揺れる簡易的なテキスト処理で使えます。

5-3. Compiled + CultureInvariantの使い方

Compiled + CultureInvariantは、繰り返し使う機械的な文字列判定に向いています。

C#
var extensionRegex = new Regex(
@"\.(jpg|jpeg|png|gif)$",
RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.Compiled
);

Console.WriteLine(extensionRegex.IsMatch("IMAGE.PNG")); // True

ファイル拡張子やコード値のように、自然言語のルールではなく固定的な仕様に基づいて判定したい場合に使いやすい組み合わせです。

5-4. IgnorePatternWhitespace + ExplicitCaptureの使い方

複雑な抽出処理では、IgnorePatternWhitespace + ExplicitCaptureが役立ちます。

C#
string pattern = @"
^
(?<year>\d{4}) # 年
-
(?<month>\d{2}) # 月
-
(?<day>\d{2}) # 日
$
";

var options = RegexOptions.IgnorePatternWhitespace
| RegexOptions.ExplicitCapture;

Match match = Regex.Match("2026-06-18", pattern, options);

Console.WriteLine(match.Groups["year"].Value); // 2026
Console.WriteLine(match.Groups["month"].Value); // 06
Console.WriteLine(match.Groups["day"].Value); // 18

明示的に名前を付けたグループだけを取り出せるため、不要なキャプチャを減らし、コードの意図を明確にできます。

5-5. 組み合わせるときの注意点

RegexOptionsは自由に組み合わせられるように見えますが、一部の組み合わせには制限があります。

特に注意すべきなのはRegexOptions.ECMAScriptです。ECMAScriptは、IgnoreCaseMultilineCompiledとのみ組み合わせ可能で、それ以外のオプションと組み合わせると例外が発生します。Microsoft Learn

C#
// OK
var ok = RegexOptions.ECMAScript | RegexOptions.IgnoreCase;

// NG
var ng = RegexOptions.ECMAScript | RegexOptions.Singleline;

また、MultilineSinglelineは名前が似ていますが、変更する対象が違います。Multiline^$Singleline.の動作を変更します。

5-6. 実務でよく使う組み合わせ早見表

組み合わせ用途
IgnoreCaseキーワード検索、拡張子判定
IgnoreCase | Multilineログの行単位検索
Singleline | IgnoreCase複数行ブロックの簡易抽出
IgnorePatternWhitespace | IgnoreCase読みやすい入力チェック
IgnorePatternWhitespace | ExplicitCapture複雑な抽出処理
Compiled | CultureInvariant繰り返し使う固定ルールの判定
IgnoreCase | CultureInvariant | NonBacktracking安定性を重視した入力チェック

6. RegexOptionsで混同しやすいポイント

6-1. MultilineとSinglelineの違い

MultilineSinglelineは、名前だけ見ると混同しやすいオプションです。

違いは次のとおりです。

オプション変わるもの主な用途
Multiline^$行単位の先頭・末尾判定
Singleline.改行を含む範囲マッチ

Multilineを指定しても、.が改行に一致するようにはなりません。

C#
string text = "A\nB";
Console.WriteLine(Regex.IsMatch(text, "A.B", RegexOptions.Multiline)); // False

改行を含めて.でマッチしたい場合はSinglelineを使います。

C#
Console.WriteLine(Regex.IsMatch(text, "A.B", RegexOptions.Singleline)); // True

6-2. IgnoreCaseとCultureInvariantの関係

IgnoreCaseは大文字・小文字を無視するオプションです。一方、CultureInvariantはカルチャ差の影響を抑えるオプションです。

C#
var options = RegexOptions.IgnoreCase | RegexOptions.CultureInvariant;

英数字、識別子、ファイル拡張子、プロトコル名などを扱う場合は、この組み合わせが有効です。

自然言語の文字列をユーザーの文化圏に合わせて処理したい場合は、安易にCultureInvariantを使うのではなく、要件に応じて判断しましょう。

6-3. Compiledは常に速いわけではない理由

RegexOptions.Compiledは「マッチ処理」を高速化できる可能性がありますが、「Regexオブジェクトの作成」は重くなります。

そのため、次のようなケースでは逆効果になる場合があります。

C#
// 1回しか使わないのにCompiledを指定する例
bool result = Regex.IsMatch(
"2026-06-18",
@"^\d{4}-\d{2}-\d{2}$",
RegexOptions.Compiled
);

1回だけの処理なら、コンパイルの初期化コストを回収できません。Microsoftのベストプラクティスでも、解釈型、コンパイル済み、ソース生成のどれが最適かは、正規表現の複雑さや処理するデータなど複数の要因に依存し、Stopwatchで比較できると説明されています。Microsoft Learn

6-4. IgnorePatternWhitespaceで空白をマッチさせたい場合の注意

IgnorePatternWhitespaceを指定すると、パターン内のエスケープされていない空白は無視されます。

C#
string pattern = @"A B";

bool result = Regex.IsMatch(
"A B",
pattern,
RegexOptions.IgnorePatternWhitespace
);

Console.WriteLine(result); // False

この場合、A BではなくABというパターンに近い扱いになります。

空白を明示的にマッチさせたい場合は、次のように書きます。

C#
Regex.IsMatch("A B", @"A\sB", RegexOptions.IgnorePatternWhitespace);
Regex.IsMatch("A B", @"A[ ]B", RegexOptions.IgnorePatternWhitespace);
Regex.IsMatch("A B", @"A\ B", RegexOptions.IgnorePatternWhitespace);

6-5. ECMAScript指定時に使えない組み合わせ

ECMAScriptは、組み合わせ制限が強いオプションです。

使える組み合わせは、基本的に次の3つです。

C#
RegexOptions.ECMAScript | RegexOptions.IgnoreCase
RegexOptions.ECMAScript | RegexOptions.Multiline
RegexOptions.ECMAScript | RegexOptions.Compiled

これら以外、たとえばSinglelineCultureInvariantなどと組み合わせると例外が発生します。

C#
// 例外になる組み合わせ
var options = RegexOptions.ECMAScript | RegexOptions.CultureInvariant;

ECMAScriptを指定する必要がある場面は限られます。通常の.NET正規表現として処理できるなら、無理に使う必要はありません。

6-6. NonBacktrackingが適しているケース・適していないケース

NonBacktrackingが適しているのは、次のようなケースです。

適しているケース理由
入力チェック線形時間処理により安全性を高めやすい
ユーザー入力を扱う処理ReDoSリスクを抑えやすい
単純な抽出・検証バックトラッキング不要なパターンと相性がよい
大量データ処理最悪ケースの遅延を抑えやすい

一方、後方参照、複雑な先読み・後読み、バックトラッキング前提のパターンなどでは適さない場合があります。Microsoftのバックトラッキング解説でも、後読み・先読み・後方参照・アトミックグループなど、バックトラッキングを必要とする構成を使わない場合はRegexOptions.NonBacktrackingを検討できると説明されています。Microsoft Learn

7. RegexOptionsを使った実践サンプル集

7-1. ログファイルからエラー行を抽出する

ログファイルからERRORで始まる行を取り出すサンプルです。

C#
using System.Text.RegularExpressions;

string log = """
INFO 2026-06-18 Started
WARN 2026-06-18 Slow response
ERROR 2026-06-18 File not found
error 2026-06-18 Access denied
""";

var options = RegexOptions.IgnoreCase | RegexOptions.Multiline;

foreach (Match match in Regex.Matches(log, @"^error\s+.*$", options))
{
Console.WriteLine(match.Value);
}

IgnoreCaseERRORerrorを同一視し、Multilineで行単位の検索にしています。

7-2. 複数行のHTML・XML風テキストから要素を取り出す

複数行のブロックを抽出する例です。

C#
string text = """
<item>
<name>Book</name>
<price>1200</price>
</item>
""";

string pattern = @"<item>.*?</item>";

Match match = Regex.Match(text, pattern, RegexOptions.Singleline);

Console.WriteLine(match.Value);

Singlelineを指定することで、.が改行を含めて一致します。

ただし、入れ子構造があるHTMLやXMLでは正規表現だけで正確に解析するのが難しくなります。実務では、対象テキストの構造が単純であることを確認して使いましょう。

7-3. CSVや設定ファイルのコメント行を判定する

CSVや設定ファイルで、#から始まるコメント行を判定する例です。

C#
string config = """
# comment
host=localhost
port=5432
# timeout=30
""";

var options = RegexOptions.Multiline;

foreach (Match match in Regex.Matches(config, @"^\s*#.*$", options))
{
Console.WriteLine(match.Value);
}

^\s*#によって、行頭に空白があってもコメント行として扱えます。

7-4. 日本語・英数字を含む文字列を大小文字無視で検索する

日本語と英数字が混在するテキストから、英字キーワードを大小文字無視で検索する例です。

C#
string text = "C#のRegexOptionsを使うと、REGEXの動作を変更できます。";

bool result = Regex.IsMatch(
text,
"regex",
RegexOptions.IgnoreCase | RegexOptions.CultureInvariant
);

Console.WriteLine(result); // True

日本語部分には大文字・小文字の概念がありませんが、英字部分の検索ではIgnoreCaseが有効です。機械的なキーワード検索では、CultureInvariantも組み合わせると環境差を抑えやすくなります。

7-5. 入力チェックでRegexOptionsを安全に使う

ユーザーIDの入力チェック例です。

C#
string userId = "user_123";

var options = RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.NonBacktracking;

bool isValid = Regex.IsMatch(
userId,
@"^[a-z0-9_]{3,20}$",
options
);

Console.WriteLine(isValid); // True

入力チェックでは、次の点を意識します。

ポイント理由
^$で全体一致させる部分一致によるすり抜けを防ぐ
長さ制限を入れる過度に長い入力を避ける
NonBacktrackingを検討するパフォーマンスリスクを抑える
タイムアウトを指定する想定外の遅延を防ぐ

7-6. RegexOptionsとタイムアウト指定を組み合わせる

外部入力やユーザー入力に正規表現を使う場合は、タイムアウト指定が重要です。

C#
using System;
using System.Text.RegularExpressions;

string input = "aaaaaaaaaaaaaaaaaaaaaaaaaaaa!";
string pattern = @"^(a+)+$";

try
{
var regex = new Regex(
pattern,
RegexOptions.None,
TimeSpan.FromMilliseconds(500)
);

bool result = regex.IsMatch(input);
Console.WriteLine(result);
}
catch (RegexMatchTimeoutException)
{
Console.WriteLine("正規表現の処理がタイムアウトしました。");
}

Microsoftのベストプラクティスでは、信頼できない入力をSystem.Text.RegularExpressionsで処理する場合はタイムアウトを渡すべきだと警告されています。Microsoft Learn

8. RegexOptions使用時のパフォーマンスと安全性

8-1. Compiledを使うべきケース

RegexOptions.Compiledを使うべきなのは、同じ正規表現を何度も使うケースです。

C#
static readonly Regex EmailRegex = new Regex(
@"^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$",
RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.Compiled
);

次のような場面に向いています。

ケース理由
アプリ起動中ずっと使う初期化コストを回収しやすい
大量データに繰り返し適用するマッチ処理の高速化が期待できる
同じ入力チェックを何度も行う再利用しやすい
静的フィールドで保持する作成コストを抑えやすい

8-2. Compiledを避けたほうがよいケース

Compiledを避けたほうがよいのは、次のようなケースです。

ケース理由
1回だけ使う初期化コストが無駄になりやすい
パターンが毎回変わるコンパイル結果を再利用しづらい
短い入力を少量処理する高速化の効果が小さい
起動速度を重視する初回コストが目立つ場合がある

Compiledは魔法の高速化オプションではありません。実際に速くなるかは、Stopwatchやベンチマークで測るのが確実です。

8-3. 正規表現のキャッシュとRegexOptionsの関係

C#のRegexには、静的メソッド呼び出しで使われる正規表現パターンのキャッシュがあります。Microsoftのドキュメントでは、正規表現エンジンはアプリケーション全体のキャッシュを保持し、静的メソッド呼び出しで使われるパターンを保存すると説明されています。また、既定では最大15個の正規表現をキャッシュするとされています。Microsoft Learn

C#
Regex.IsMatch("abc", "abc", RegexOptions.IgnoreCase);
Regex.IsMatch("ABC", "abc", RegexOptions.IgnoreCase);

同じパターンとオプションを繰り返し使う場合、キャッシュの効果を受けられる可能性があります。

ただし、大量の異なるパターンを次々に使う場合は、キャッシュから追い出されることもあります。繰り返し使う重要な正規表現は、Regexインスタンスとして保持する設計も検討しましょう。

8-4. ReDoS対策としてのタイムアウト指定

ReDoSとは、正規表現のバックトラッキングを悪用して処理を極端に遅くする攻撃や問題のことです。

特に、次のようなパターンは注意が必要です。

C#
@"^(a+)+$"

このようなネストした量指定子は、入力によって大量のバックトラッキングを発生させる可能性があります。

対策としては、次のような方法があります。

対策内容
タイムアウトを指定する長時間処理を打ち切る
入力長を制限する巨大な入力を処理しない
パターンを単純化するバックトラッキングを減らす
NonBacktrackingを使う線形時間処理を狙う
ユーザー入力をパターンにしない悪意あるパターンを避ける

Microsoftのバックトラッキング解説でも、タイムアウトを明示的に設定しない場合、既定ではRegex.InfiniteMatchTimeoutとなり、正規表現エンジンはタイムアウトしないと説明されています。Microsoft Learn

8-5. NonBacktrackingによるパフォーマンス改善

RegexOptions.NonBacktrackingは、バックトラッキングによる最悪ケースの遅延を避けたい場合に有効です。

C#
var regex = new Regex(
@"^[a-z0-9_-]{3,20}$",
RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.NonBacktracking
);

単純な入力チェック、ID検証、固定フォーマット判定などでは相性がよいです。

ただし、NonBacktrackingはすべての正規表現構文に対応するわけではありません。既存の複雑なパターンに追加する場合は、テストを行い、期待どおりにマッチするか確認する必要があります。

8-6. 大量データ処理での設計ポイント

大量データに正規表現を使う場合は、RegexOptionsだけではなく、設計全体を考えることが重要です。

設計ポイント内容
Regexインスタンスを再利用する作成コストを減らす
入力を分割して処理する1回あたりの処理量を抑える
タイムアウトを指定する異常系で止まらないようにする
必要以上に.*を使わないバックトラッキングを減らす
Compiledを測定して判断する効果がある場合だけ使う
NonBacktrackingを検討する安定した処理時間を狙う

大量データ処理では、「とりあえずCompiled」ではなく、入力サイズ、パターンの複雑さ、呼び出し回数、タイムアウト、安全性をまとめて考える必要があります。

9. RegexOptionsのエラー・トラブル対処

9-1. オプションを組み合わせたら期待通りにマッチしない

複数のRegexOptionsを組み合わせた結果、期待通りにマッチしない場合は、まず各オプションが何を変更するかを確認しましょう。

よくある原因は次のとおりです。

原因確認ポイント
MultilineSinglelineの混同^/$なのか.なのか
IgnorePatternWhitespaceで空白が消えている空白を\s[ ]で書いているか
ECMAScriptの制限組み合わせ可能なオプションか
ExplicitCaptureでグループが取れない名前付きキャプチャにしているか
CultureInvariantの影響カルチャ依存の比較を期待していないか

複雑な組み合わせを使う場合は、一度オプションを1つずつ有効にして、どのオプションで挙動が変わるか確認すると原因を特定しやすくなります。

9-2. Multilineを指定しても複数行全体にマッチしない

Multilineは、複数行全体を.でマッチさせるオプションではありません。

C#
string text = "A\nB";

bool result = Regex.IsMatch(text, "A.B", RegexOptions.Multiline);

Console.WriteLine(result); // False

Multilineが変えるのは^$です。.で改行も含めたい場合は、Singlelineを使います。

C#
bool result = Regex.IsMatch(text, "A.B", RegexOptions.Singleline);

Console.WriteLine(result); // True

9-3. Singlelineを指定しても行頭・行末の判定が変わらない

Singleline.の動作を変えるオプションです。^$の行単位判定は変わりません。

C#
string text = """
A
B
""";

bool result = Regex.IsMatch(text, "^B", RegexOptions.Singleline);

Console.WriteLine(result); // False

行単位で^Bをマッチさせたい場合は、Multilineを使います。

C#
bool result = Regex.IsMatch(text, "^B", RegexOptions.Multiline);

Console.WriteLine(result); // True

複数行テキストで、.も改行に一致させ、さらに^$も行単位で使いたい場合は、両方を組み合わせます。

C#
var options = RegexOptions.Singleline | RegexOptions.Multiline;

9-4. IgnorePatternWhitespaceでパターン内の空白が消える

IgnorePatternWhitespaceを指定すると、パターン内の空白が無視されます。

C#
bool result = Regex.IsMatch(
"A B",
@"A B",
RegexOptions.IgnorePatternWhitespace
);

Console.WriteLine(result); // False

空白をマッチさせたい場合は、次のように明示します。

C#
Regex.IsMatch("A B", @"A\sB", RegexOptions.IgnorePatternWhitespace);
Regex.IsMatch("A B", @"A[ ]B", RegexOptions.IgnorePatternWhitespace);
Regex.IsMatch("A B", @"A\ B", RegexOptions.IgnorePatternWhitespace);

また、#以降はコメントとして扱われるため、#自体をマッチさせたい場合もエスケープが必要です。

C#
Regex.IsMatch("#tag", @"\#tag", RegexOptions.IgnorePatternWhitespace);

9-5. ECMAScript指定で例外が出る

RegexOptions.ECMAScriptで例外が出る場合、ほとんどは組み合わせ制限が原因です。

C#
// NG
var options = RegexOptions.ECMAScript | RegexOptions.Singleline;

ECMAScriptと組み合わせられるのは、IgnoreCaseMultilineCompiledのみです。Microsoft Learn

C#
// OK
var options = RegexOptions.ECMAScript
| RegexOptions.IgnoreCase
| RegexOptions.Multiline;

通常の.NET正規表現として問題ない場合は、ECMAScriptを外すのが簡単な解決策です。

9-6. Compiledにしても速くならない

Compiledにしても速くならない場合は、次の点を確認します。

確認項目内容
Regexを毎回newしていないか作成コストが増える
1回しか使っていないかコンパイルコストを回収できない
パターンが単純すぎないか差が出にくい
入力が短すぎないか高速化の効果が小さい
ボトルネックが別にないかI/Oや文字列処理が原因の場合もある

改善したい場合は、Regexstatic readonlyで再利用する、Stopwatchで計測する、必要に応じて.NETの正規表現ソースジェネレーターを検討する、といった方法があります。Microsoftのドキュメントでも、.NET 7以降では正規表現のソース生成が利用でき、可能な場合はRegexOptions.Compiledの代わりにソース生成正規表現を使うことが推奨されています。Microsoft Learn

まとめ

C#のRegexOptionsは、正規表現の動作を柔軟に変更するための重要な仕組みです。

大文字・小文字を無視するIgnoreCase、行単位で検索するMultiline、改行を含めて.でマッチさせるSingleline、読みやすいパターンを書くためのIgnorePatternWhitespace、繰り返し処理で性能向上を狙うCompiled、環境差を抑えるCultureInvariant、バックトラッキングを抑えるNonBacktrackingなど、用途に応じて適切なオプションを選ぶことで、正規表現をより安全で保守しやすくできます。

特に実務では、次の考え方が重要です。

目的おすすめのRegexOptions
大文字・小文字を無視したいIgnoreCase
行単位で検索したいMultiline
改行を含む範囲を取りたいSingleline
複雑な正規表現を読みやすくしたいIgnorePatternWhitespace
不要なキャプチャを減らしたいExplicitCapture
何度も使う正規表現を高速化したいCompiled
環境差を抑えたいCultureInvariant
末尾側から検索したいRightToLeft
ReDoSリスクを抑えたいNonBacktrackingとタイムアウト

RegexOptionsは便利ですが、組み合わせによっては意図しない挙動になることもあります。MultilineSinglelineの違い、IgnorePatternWhitespaceで空白が無視される点、ECMAScriptの組み合わせ制限、Compiledの初期化コスト、NonBacktrackingの対応構文には注意しましょう。

正規表現は強力な反面、複雑になりやすい機能です。RegexOptionsを正しく使えば、C#での文字列検索、入力チェック、ログ解析、データ抽出をより読みやすく、安全で高性能に実装できます。