C#の文字列置換を完全解説|Replace・Regex.Replaceの使い方と削除・改行・正規表現の実例

はじめに

C#で文字列の一部を別の文字列へ変更する場合、基本的にはString.Replaceメソッドを使用します。固定された文字や文字列を置換するだけであれば、簡潔に記述できるReplaceが適しています。

一方、「数字だけを削除する」「複数種類の改行をまとめて置換する」「特定の形式の日付を変換する」といったパターンベースの処理には、Regex.Replaceによる正規表現置換が便利です。

この記事では、C#の文字列置換について、次の内容を実例付きで解説します。

  • String.Replaceによる基本的な文字列置換

  • 文字列や空白、改行の削除

  • Regex.Replaceを使った正規表現置換

  • キャプチャグループによる並び替え

  • 大文字・小文字を区別しない置換

  • 置換できない場合の原因と対処法

  • 安全かつ効率的に置換するためのポイント

用途に応じてReplaceRegex.ReplaceRemoveTrimを使い分けられるようになりましょう。

1. C#で文字列を置換する方法

1-1. String.Replaceメソッドで文字列を置換する基本構文

C#で固定文字列を置換する基本構文は、次のとおりです。

string 置換後の文字列 = 元の文字列.Replace("置換前", "置換後");

例えば、文字列内の「東京」を「大阪」に置換する場合は、次のように記述します。

string text = "東京へ行きます。";string result = text.Replace("東京", "大阪");

Console.WriteLine(result);

実行結果は次のとおりです。

大阪へ行きます。

String.Replaceは、検索条件として正規表現を使用しません。指定した文字または文字列と完全に一致する部分が置換対象になります。

1-2. 文字を置換するchar型のReplace

1文字を別の1文字へ置換する場合は、char型を受け取るReplaceを使用できます。

string text = "2026/06/20";string result = text.Replace('/', '-');

Console.WriteLine(result);

実行結果は次のとおりです。

2026-06-20

char型の値はシングルクォーテーションで囲みます。

text.Replace('a', 'A');

このオーバーロードでは、置換前と置換後のどちらにも1文字しか指定できません。1文字を複数文字へ変更したい場合は、string型のReplaceを使用します。

string text = "A-B";string result = text.Replace("-", "から");

1-3. 部分文字列を置換するstring型のReplace

複数文字からなる部分文字列を置換する場合は、string型のReplaceを使用します。

string text = "C#を勉強しています。";string result = text.Replace("勉強", "学習");

Console.WriteLine(result);

実行結果は次のとおりです。

C#を学習しています。

文字列はダブルクォーテーションで囲みます。

text.Replace("置換前", "置換後");

置換対象の文字列が見つからない場合、内容は変更されません。

string text = "Hello";string result = text.Replace("C#", "Java");

Console.WriteLine(result); // Hello

1-4. Replaceは一致するすべての文字列を置換する

String.Replaceは、最初に見つかった部分だけでなく、一致するすべての部分を置換します。

string text = "赤、赤、青、赤";string result = text.Replace("赤", "白");

Console.WriteLine(result);

実行結果は次のとおりです。

白、白、青、白

置換回数を1回だけに制限する機能は、通常のString.Replaceにはありません。最初の1件だけを置換したい場合は、IndexOfと文字列操作を組み合わせるか、Regex.Replaceの置換回数指定を使用します。

1-5. Replaceは元の文字列を変更せず新しい文字列を返す

C#のstringはイミュータブル、つまり作成後に内容を直接変更できない型です。そのため、Replaceを実行しても元の文字列は変更されません。

string text = "Hello C#";

text.Replace("C#", "World");

Console.WriteLine(text);

実行結果は次のとおりです。

Hello C#

置換結果を使用するには、戻り値を変数へ代入します。

string text = "Hello C#";

text = text.Replace("C#", "World");

Console.WriteLine(text);

実行結果は次のとおりです。

Hello World

別の変数へ代入して、元の文字列を残すこともできます。

string original = "Hello C#";string replaced = original.Replace("C#", "World");

2. String.Replaceを使った基本的な置換例

2-1. 指定した文字列を別の文字列に置換する

商品名などの一部を変更する例を見てみましょう。

string productName = "スタンダードプラン";string result = productName.Replace("スタンダード", "プレミアム");

Console.WriteLine(result);

実行結果は次のとおりです。

プレミアムプラン

Replaceでは部分一致した箇所がすべて置換されます。

string text = "test-data-test";string result = text.Replace("test", "sample");

Console.WriteLine(result); // sample-data-sample

2-2. 特定の1文字を別の文字に置換する

区切り文字を変更する場合は、char型のReplaceが便利です。

string date = "2026.06.20";string result = date.Replace('.', '/');

Console.WriteLine(result); // 2026/06/20

文字列中の小文字を大文字へ置換することもできます。

string text = "banana";string result = text.Replace('a', 'A');

Console.WriteLine(result); // bAnAnA

ただし、文字列全体を大文字にする目的であれば、ToUpperToUpperInvariantを使用するほうが明確です。

2-3. 日本語を含む文字列を置換する

String.Replaceは日本語の文字列にも使用できます。

string message = "本日の営業時間は9時から17時です。";string result = message.Replace("17時", "18時");

Console.WriteLine(result);

実行結果は次のとおりです。

本日の営業時間は9時から18時です。

漢字やひらがな、カタカナも通常の文字列として処理できます。

string text = "サーバーに接続しました。";string result = text.Replace("サーバー", "データベース");

Console.WriteLine(result);

2-4. 複数の文字列を連続して置換する

複数の固定文字列を置換する場合は、Replaceを連続して呼び出せます。

string text = "東京都新宿区";string result = text.Replace("東京都", "東京").Replace("新宿区", "渋谷区");

Console.WriteLine(result); // 東京渋谷区

置換条件が多い場合は、配列や辞書を使ってループ処理にすると管理しやすくなります。

string text = "赤と青と緑";

var replacements = new Dictionary<string, string>{["赤"] = "Red",["青"] = "Blue",["緑"] = "Green"};

foreach (var pair in replacements){text = text.Replace(pair.Key, pair.Value);}

Console.WriteLine(text); // RedとBlueとGreen

置換順序によって結果が変わることがあるため、相互に含まれる文字列を置換するときは注意が必要です。

2-5. 変数を使って置換前・置換後の文字列を指定する

置換前と置換後の値は、変数で指定できます。

string text = "商品Aの価格は1,000円です。";string oldValue = "1,000円";string newValue = "1,200円";

string result = text.Replace(oldValue, newValue);

Console.WriteLine(result);

ユーザー入力や設定ファイルの値を利用する場合も、同じ書き方で置換できます。

string template = "{name}さん、こんにちは。";string name = "田中";

string result = template.Replace("{name}", name);

Console.WriteLine(result); // 田中さん、こんにちは。

複数のプレースホルダーを扱う場合は、置換漏れや置換順序にも注意しましょう。

2-6. 大文字・小文字を区別せずに置換する

通常のReplaceは、大文字と小文字を区別します。

string text = "CSharp csharp CSHARP";string result = text.Replace("csharp", "C#");

Console.WriteLine(result); // CSharp C# CSHARP

大文字・小文字を区別せず置換するには、比較方法を指定できるオーバーロードを使用します。

string text = "CSharp csharp CSHARP";

string result = text.Replace("csharp","C#",StringComparison.OrdinalIgnoreCase);

Console.WriteLine(result); // C# C# C#

このオーバーロードは、比較的新しい.NETで利用できます。古い.NET Frameworkなど、利用環境に対応するオーバーロードがない場合は、Regex.Replaceを使用する方法があります。

using System.Text.RegularExpressions;

string text = "CSharp csharp CSHARP";

string result = Regex.Replace(text,"csharp","C#",RegexOptions.IgnoreCase);

2-7. StringComparisonを指定して比較方法を制御する

StringComparisonを指定すると、文字列をどの規則で比較するかを制御できます。

string result = text.Replace(oldValue,newValue,StringComparison.Ordinal);

代表的な値は次のとおりです。

比較方法
OrdinalUnicodeコード値に基づいて比較する
OrdinalIgnoreCase大文字・小文字を無視してコード値で比較する
CurrentCulture現在のカルチャ規則で比較する
CurrentCultureIgnoreCase現在のカルチャ規則で大文字・小文字を無視する
InvariantCultureカルチャに依存しない規則で比較する
InvariantCultureIgnoreCaseカルチャに依存せず大文字・小文字を無視する

プログラム内部の識別子、コード、ファイル形式などを扱う場合は、動作が環境に左右されにくいOrdinalまたはOrdinalIgnoreCaseが一般的です。

人間が読む自然言語を文化的な規則に従って比較したい場合は、CurrentCulture系を検討します。

3. C#で文字列を削除する方法

3-1. Replaceで対象文字列を空文字に置換して削除する

文字列の一部を削除したい場合は、置換後の文字列に空文字""を指定します。

string text = "商品価格:1,000円(税込)";string result = text.Replace(税込)", "");

Console.WriteLine(result); // 商品価格:1,000円

string.Emptyを指定しても同じ結果になります。

string result = text.Replace(税込)", string.Empty);

string型のReplaceでは、置換後の値としてnullを渡した場合も、対象部分を削除する動作になります。ただし、意図が伝わりやすいstring.Emptyを使用するほうが明確です。

3-2. 特定の文字だけを削除する

char型のReplaceでは、置換後に空文字を指定できません。1文字だけを削除する場合でも、文字列として指定します。

string text = "123-456-789";string result = text.Replace("-", "");

Console.WriteLine(result); // 123456789

複数種類の文字を削除する場合は、Replaceを連続して呼び出せます。

string text = "(03)-1234-5678";

string result = text.Replace("(", "").Replace(")", "").Replace("-", "");

Console.WriteLine(result); // 0312345678

3-3. スペースやタブを削除する

半角スペースを削除する場合は、次のように記述します。

string text = "C# 文字列 置換";string result = text.Replace(" ", "");

Console.WriteLine(result); // C#文字列置換

タブはエスケープシーケンス\tで表します。

string text = "商品名\t価格\t在庫";string result = text.Replace("\t", "");

Console.WriteLine(result); // 商品名価格在庫

スペースとタブを両方削除する場合は、連続して置換します。

string result = text.Replace(" ", "").Replace("\t", "");

連続する空白文字をまとめて処理したい場合は、正規表現の\sも利用できます。ただし、\sには改行なども含まれるため、削除範囲を確認して使用してください。

3-4. 全角スペースと半角スペースをまとめて削除する

日本語の文章には、半角スペースと全角スペースが混在することがあります。

string text = "C# 文字列 置換";

string result = text.Replace(" ", "").Replace(" ", "");

Console.WriteLine(result); // C#文字列置換

2つ目の" "は全角スペースです。

正規表現を使用する場合は、次のように記述できます。

using System.Text.RegularExpressions;

string text = "C# 文字列 置換";string result = Regex.Replace(text, "[  ]", "");

Console.WriteLine(result); // C#文字列置換

文字列全体の全角・半角を統一したい場合は、Unicode正規化の利用も考えられます。ただし、正規化によって記号なども変換される可能性があるため、対象データに適した処理か確認が必要です。

3-5. 文字列の先頭・末尾の空白をTrimで削除する

文字列の先頭と末尾にある空白だけを削除する場合は、Trimを使用します。

string text = "   C#文字列置換   ";string result = text.Trim();

Console.WriteLine($"[{result}]"); // [C#文字列置換]

先頭だけを削除する場合はTrimStart、末尾だけを削除する場合はTrimEndを使用します。

string text = "   C#   ";

Console.WriteLine($"[{text.TrimStart()}]"); // [C# ]Console.WriteLine($"[{text.TrimEnd()}]"); // [ C#]

Trimは文字列中間の空白を削除しません。

string text = "  C# 文字列  ";string result = text.Trim();

Console.WriteLine(result); // C# 文字列

3-6. 指定位置の文字列をRemoveで削除する

削除する位置が決まっている場合は、Removeを使用できます。

string text = "ABCDE";string result = text.Remove(2, 2);

Console.WriteLine(result); // ABE

第1引数は削除開始位置、第2引数は削除する文字数です。位置は0から数えます。

A B C D E0 1 2 3 4

指定位置から末尾までを削除する場合は、第2引数を省略できます。

string text = "ABCDE";string result = text.Remove(2);

Console.WriteLine(result); // AB

範囲外の位置や文字数を指定すると例外が発生するため、事前に文字列長を確認しましょう。

3-7. Replace・Remove・Trimの使い分け

3つのメソッドは、目的に応じて使い分けます。

メソッド適した用途
Replace特定の文字や文字列を検索して置換・削除する
Remove位置と文字数を指定して削除する
Trim先頭・末尾の空白を削除する

例えば、「すべてのハイフンを削除する」場合はReplaceが適しています。

string result = text.Replace("-", "");

「先頭から3文字を削除する」場合はRemoveを使用します。

string result = text.Remove(0, 3);

「入力値の前後に付いた余分な空白を削除する」場合はTrimが適しています。

string result = text.Trim();

4. C#で改行を置換・削除する方法

4-1. Environment.NewLineを使って改行を置換する

現在の実行環境で使用される改行文字列は、Environment.NewLineで取得できます。

string text = $"1行目{Environment.NewLine}2行目";

string result = text.Replace(Environment.NewLine," / ");

Console.WriteLine(result);

実行結果は次のとおりです。

1行目 / 2行目

Environment.NewLineを使用すると、実行環境の標準的な改行コードを直接記述せずに扱えます。

ただし、外部ファイルやネットワークから受け取った文字列には、実行環境と異なる改行コードが含まれることがあります。その場合、Environment.NewLineだけではすべての改行を処理できません。

4-2. 改行を空文字に置換して削除する

改行を削除する場合は、空文字へ置換します。

string text = $"C#{Environment.NewLine}文字列{Environment.NewLine}置換";string result = text.Replace(Environment.NewLine, "");

Console.WriteLine(result); // C#文字列置換

文字列リテラルで\r\nを削除することもできます。

string text = "1行目\r\n2行目";string result = text.Replace("\r\n", "");

ただし、\nだけの改行や\rだけの改行には一致しません。

4-3. 改行をスペースや任意の文字列に置換する

文章を1行へまとめる場合、改行を削除すると単語同士がつながることがあります。そのため、スペースへ置換する方法が適しています。

string text = $"C#の{Environment.NewLine}文字列置換を{Environment.NewLine}解説します。";

string result = text.Replace(Environment.NewLine," ");

Console.WriteLine(result);

実行結果は次のとおりです。

C#の 文字列置換を 解説します。

区切り文字へ変更することもできます。

string result = text.Replace(Environment.NewLine, "|");

4-4. CRLF・LF・CRの違い

代表的な改行コードは次の3種類です。

名称表記内容
CRLF\r\nキャリッジリターンとラインフィード
LF\nラインフィード
CR\rキャリッジリターン

Windowsでは一般にCRLF、Linuxや現在のmacOSではLFが使われます。CRは旧式のMac環境や一部のデータで見られることがあります。

外部から読み込んだデータでは、複数の改行コードが混在している可能性があります。そのため、改行処理では入力元を考慮する必要があります。

4-5. Windows・Linux・macOSの改行コードをまとめて処理する

複数種類の改行をString.Replaceで処理する場合は、CRLFを先に置換します。

string text = "1行目\r\n2行目\n3行目\r4行目";

string result = text.Replace("\r\n", " ").Replace("\n", " ").Replace("\r", " ");

Console.WriteLine(result);

実行結果は次のとおりです。

1行目 2行目 3行目 4行目

\n\rを先に置換すると、CRLFを構成する片方だけが処理される可能性があります。長い文字列である\r\nから先に置換することが重要です。

4-6. Regex.Replaceで複数種類の改行コードを一括置換する

正規表現を使用すれば、CRLF、LF、CRを1回の処理で置換できます。

using System.Text.RegularExpressions;

string text = "1行目\r\n2行目\n3行目\r4行目";string result = Regex.Replace(text, @"\r\n|\n|\r", " ");

Console.WriteLine(result);

より簡潔に、\r\n?|\nと記述することもできます。

string result = Regex.Replace(text, @"\r\n?|\n", " ");

このパターンは、次の改行に一致します。

  • \r\n

  • \r

  • \n

4-7. 連続する改行を1つにまとめる

連続する改行を1つの改行へまとめる場合は、正規表現の量指定子を使用します。

using System.Text.RegularExpressions;

string text = "1行目\r\n\r\n\r\n2行目\n\n3行目";

string result = Regex.Replace(text,@"(?:\r\n|\r|\n)+",Environment.NewLine);

Console.WriteLine(result);

空白だけの行もまとめたい場合は、改行前後のスペースやタブをパターンへ含めます。

string result = Regex.Replace(text,@"(?:[ \t](?:\r\n|\r|\n)){2,}",Environment.NewLine);

必要以上に広い範囲へ一致しないよう、実際の入力例を使って確認することが大切です。

5. Regex.Replaceで正規表現による置換を行う方法

5-1. Regex.Replaceの基本構文

Regex.Replaceは、正規表現パターンに一致した部分を置換するメソッドです。

string result = Regex.Replace(入力文字列,正規表現パターン,置換後の文字列);

例えば、すべての数字をへ置換する場合は、次のように記述します。

string text = "商品123の価格は456円です。";string result = Regex.Replace(text, @"\d", "*");

Console.WriteLine(result);

実行結果は次のとおりです。

商品の価格は円です。

\dは数字1文字を表す正規表現です。

5-2. System.Text.RegularExpressionsを読み込む

Regexクラスを使用するには、ファイルの先頭で名前空間を読み込みます。

using System.Text.RegularExpressions;

名前空間を読み込まない場合は、完全修飾名でも呼び出せます。

string result = System.Text.RegularExpressions.Regex.Replace(text,@"\d+","*");

通常はusingを記述したほうがコードを簡潔にできます。

5-3. 正規表現に一致する文字列を置換する

複数桁の数字をまとめて置換する場合は、\d+を使用します。

string text = "商品123は4560円です。";string result = Regex.Replace(text, @"\d+", "[数値]");

Console.WriteLine(result);

実行結果は次のとおりです。

商品[数値][数値]円です。

+は、直前のパターンが1回以上連続することを表します。

単語の境界を指定することもできます。

string text = "cat category cat";string result = Regex.Replace(text, @"\bcat\b", "dog");

Console.WriteLine(result); // dog category dog

\bを付けることで、categoryに含まれるcatは置換されません。

5-4. 数字・英字・記号を指定して置換する

数字を置換するパターンは\dです。

string result = Regex.Replace("A1B2C3", @"\d", "");// ABC

半角英字を置換する場合は、文字クラスを使用します。

string result = Regex.Replace("abc123XYZ", @"[A-Za-z]", "*");// 123

記号を置換する場合も文字クラスを使用できます。

string text = "A-B/C.D";string result = Regex.Replace(text, @"[-/.]", "_");

Console.WriteLine(result); // A_B_C_D

文字クラス内のハイフンは範囲指定として解釈されるため、先頭か末尾へ置くか、-とエスケープします。

5-5. 正規表現に一致した文字列を削除する

置換後の文字列を空文字にすれば、一致部分を削除できます。

string text = "商品番号:AB-123-CD";string result = Regex.Replace(text, @"\d", "");

Console.WriteLine(result); // 商品番号:AB--CD

連続する数字をまとめて削除する場合は、\d+を使用します。

string result = Regex.Replace(text, @"\d+", "");

空白文字を削除する例は次のとおりです。

string text = "A B\tC\nD";string result = Regex.Replace(text, @"\s", "");

Console.WriteLine(result); // ABCD

\sには半角スペースやタブ、改行などが含まれます。

5-6. RegexOptions.IgnoreCaseで大文字・小文字を無視する

大文字・小文字を区別せずに置換する場合は、RegexOptions.IgnoreCaseを指定します。

string text = "CSharp csharp CSHARP";

string result = Regex.Replace(text,"csharp","C#",RegexOptions.IgnoreCase);

Console.WriteLine(result); // C# C# C#

カルチャに依存しない比較が必要な場合は、RegexOptions.CultureInvariantを組み合わせられます。

RegexOptions options =RegexOptions.IgnoreCase |RegexOptions.CultureInvariant;

string result = Regex.Replace(text,"csharp","C#",options);

5-7. RegexOptions.MultilineとSinglelineの違い

RegexOptions.MultilineRegexOptions.Singlelineは、名前が似ていますが役割が異なります。

Multilineは、^$を各行の先頭・末尾へ一致させます。

string text = "apple\nbanana\napple";

string result = Regex.Replace(text,"^apple$","orange",RegexOptions.Multiline);

Console.WriteLine(result);

実行結果は次のとおりです。

orangebananaorange

Singlelineは、ドット.が改行にも一致するようにします。

string text = "<start>\n内容\n<end>";

string result = Regex.Replace(text,@"<start>.*?<end>","[削除]",RegexOptions.Singleline);

Console.WriteLine(result); // [削除]

まとめると、次の違いがあります。

  • Multiline^$の動作を変更する

  • Singleline.が改行に一致するようにする

5-8. Regex.Replaceの置換回数を指定する

RegexインスタンスのReplaceメソッドでは、置換回数を指定できます。

var regex = new Regex(@"\d+");

string text = "10個、20個、30個";string result = regex.Replace(text, "[数値]", 2);

Console.WriteLine(result);

実行結果は次のとおりです。

[数値]個、[数値]個、30個

第3引数の2が最大置換回数です。

最初の1件だけを置換する場合は、1を指定します。

string result = regex.Replace(text, "[数値]", 1);

5-9. 文字列の一部だけを対象に置換する

検索開始位置を指定する場合は、RegexインスタンスのReplaceに開始位置を渡します。

var regex = new Regex(@"\d+");

string text = "123 ABC 456 DEF 789";string result = regex.Replace(text, "*", 1, 7);

Console.WriteLine(result); // 123 ABC * DEF 789

引数は、入力文字列、置換文字列、最大置換回数、検索開始位置の順です。

ただし、検索開始位置を指定しても、対象範囲の終了位置は制限されません。特定範囲内だけを厳密に置換したい場合は、対象部分を切り出してから置換します。

string text = "AAA 123 BBB 456 CCC";

int start = 4;int length = 11;

string target = text.Substring(start, length);string replaced = Regex.Replace(target, @"\d+", "*");

string result =text[..start] +replaced +text[(start + length)..];

Console.WriteLine(result); // AAA * BBB * CCC

6. Regex.Replaceでキャプチャした文字列を置換する方法

6-1. キャプチャグループの基本

正規表現の丸括弧()で囲んだ部分は、キャプチャグループとして保存されます。

string text = "2026-06-20";string pattern = @"(\d{4})-(\d{2})-(\d{2})";

このパターンでは、次の3つのグループを取得できます。

  • 第1グループ:2026

  • 第2グループ:06

  • 第3グループ:20

キャプチャした値は、置換後の文字列で再利用できます。

6-2. $1・$2を使って一致部分を置換後に再利用する

番号付きキャプチャグループは、置換文字列内で$1$2のように参照します。

string text = "山田 太郎";string pattern = @"(\S+)\s+(\S+)";

string result = Regex.Replace(text,pattern,"$2 $1");

Console.WriteLine(result); // 太郎 山田

$1は1番目のグループ、$2は2番目のグループです。

置換文字列内にドル記号自体を出力する場合は、$$と記述します。

string result = Regex.Replace("100", @"\d+", "$$$&");

Console.WriteLine(result); // $100

$&は一致した文字列全体を表します。

6-3. 名前付きキャプチャを使って置換する

キャプチャグループには名前を付けられます。

string text = "2026-06-20";

string pattern =@"(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})";

string replacement ="${year}年${month}月${day}日";

string result = Regex.Replace(text,pattern,replacement);

Console.WriteLine(result); // 2026年06月20日

名前付きキャプチャは、グループが多い場合でも意味を把握しやすくなります。

構文は次のとおりです。

(?<名前>パターン)

置換文字列では、${名前}で参照します。

6-4. 文字列の並び順を入れ替える

姓と名、コードの各部分などをキャプチャし、置換後に順番を変更できます。

string text = "Taro Yamada";string pattern = @"(\w+)\s+(\w+)";

string result = Regex.Replace(text,pattern,"$2, $1");

Console.WriteLine(result); // Yamada, Taro

商品コードの並び順を変更する例は次のとおりです。

string text = "ABC-123";string pattern = @"([A-Z]+)-(\d+)";

string result = Regex.Replace(text,pattern,"$2-$1");

Console.WriteLine(result); // 123-ABC

6-5. 日付の形式を変換する

yyyy-MM-dd形式をyyyy/MM/dd形式へ変換できます。

string text = "2026-06-20";string pattern = @"(\d{4})-(\d{2})-(\d{2})";

string result = Regex.Replace(text,pattern,"$1/$2/$3");

Console.WriteLine(result); // 2026/06/20

日本語形式へ変換する場合は、次のように記述します。

string result = Regex.Replace(text,pattern,"$1年$2月$3日");

ただし、正規表現は日付として実在するかどうかまでは判定しません。例えば2026-99-99も形式上は一致します。

日付としての妥当性確認や厳密な変換が必要な場合は、DateTime.TryParseExactを使用してください。

6-6. MatchEvaluatorを使って動的に置換する

置換後の値を計算したい場合は、MatchEvaluatorを使用します。

using System.Text.RegularExpressions;

string text = "商品Aは100円、商品Bは200円です。";

string result = Regex.Replace(text,@"\d+",new MatchEvaluator(DoubleNumber));

Console.WriteLine(result);

static string DoubleNumber(Match match){int value = int.Parse(match.Value);return (value * 2).ToString();}

実行結果は次のとおりです。

商品Aは200円、商品Bは400円です。

一致した文字列は、MatchオブジェクトのValueから取得できます。

6-7. ラムダ式で置換後の文字列を生成する

MatchEvaluatorはラムダ式で簡潔に記述できます。

string text = "10 20 30";

string result = Regex.Replace(text,@"\d+",match =>{int value = int.Parse(match.Value);return (value + 5).ToString();});

Console.WriteLine(result); // 15 25 35

1行で書ける処理なら、さらに短くできます。

string result = Regex.Replace(text,@"\d+",match => $"[{match.Value}]");

ラムダ式を使うと、一致内容、キャプチャグループ、外部変数などに応じて置換結果を動的に生成できます。

7. よく使う文字列置換の実例

7-1. 連続するスペースを1つに置換する

半角スペースが複数連続している部分を、1つのスペースへまとめます。

string text = "C#    文字列   置換";

string result = Regex.Replace(text,@" +"," ");

Console.WriteLine(result); // C# 文字列 置換

タブなども含む水平空白をまとめる場合は、次のパターンを使用できます。

string result = Regex.Replace(text, @"[ \t]+", " ");

改行も含めてすべての空白文字をまとめる場合は、\s+を使用します。

string result = Regex.Replace(text, @"\s+", " ");

7-2. HTMLタグを削除する

単純なHTML文字列からタグらしき部分を削除する例です。

string html = "<p>C#の<strong>文字列置換</strong>を解説します。</p>";

string text = Regex.Replace(html,"<.*?>","");

Console.WriteLine(text); // C#の文字列置換を解説します。

ただし、HTMLは正規表現だけで完全に解析できるほど単純な構造ではありません。属性値に>が含まれる場合や、script、style、壊れたHTMLなどでは意図しない結果になる可能性があります。

信頼できないHTMLや複雑なHTMLを扱う場合は、HTMLパーサーやサニタイズ用ライブラリを使用してください。

7-3. 数字以外の文字を削除する

数字以外を表す\Dを使用します。

string text = "電話:03-1234-5678";

string result = Regex.Replace(text,@"\D","");

Console.WriteLine(result); // 0312345678

半角の0〜9だけを残したい場合は、否定文字クラスを使用します。

string result = Regex.Replace(text, @"[^0-9]", "");

\dはUnicode上の数字にも一致するため、半角数字だけを対象にする場合は[0-9]のほうが明確です。

7-4. 英数字以外の文字を削除する

半角英数字以外を削除する場合は、次のように記述します。

string text = "AB-123_CD!";

string result = Regex.Replace(text,@"[^A-Za-z0-9]","");

Console.WriteLine(result); // AB123CD

大文字・小文字を区別しないオプションを使えば、パターンを短くできます。

string result = Regex.Replace(text,@"[^a-z0-9]","",RegexOptions.IgnoreCase);

日本語も残したい場合は、許可する文字の範囲を要件に合わせて追加する必要があります。

7-5. 特定の記号をまとめて削除する

ハイフン、スラッシュ、ピリオドをまとめて削除します。

string text = "2026-06/20.123";

string result = Regex.Replace(text,@"[-/.]","");

Console.WriteLine(result); // 20260620123

括弧も削除する場合は、パターンへ追加します。

string result = Regex.Replace("(03)-1234/5678",@"[()-/.]","");

正規表現で特別な意味を持つ記号は、文字クラス内でも位置やエスケープに注意してください。

7-6. 電話番号や郵便番号の形式を整える

数字以外を削除してから電話番号を整形する例です。

string input = "03 (1234) 5678";string digits = Regex.Replace(input, @"[^0-9]", "");

string result = Regex.Replace(digits,@"^(\d{2})(\d{4})(\d{4})$","$1-$2-$3");

Console.WriteLine(result); // 03-1234-5678

郵便番号を整形する例は次のとおりです。

string input = "1234567";string result = Regex.Replace(input,@"^(\d{3})(\d{4})$","$1-$2");

Console.WriteLine(result); // 123-4567

電話番号は桁数や市外局番の形式が複数あるため、実際の要件に応じた検証が必要です。

7-7. 日付文字列の区切り文字を置換する

ハイフン、ピリオド、スラッシュのいずれかを、スラッシュへ統一します。

string text = "2026-06.20";

string result = Regex.Replace(text,@"[-.]","/");

Console.WriteLine(result); // 2026/06/20

日付全体の形式を確認しながら変換する場合は、キャプチャグループを使用します。

string result = Regex.Replace(text,@"^(\d{4})[-./](\d{2})[-./](\d{2})$","$1/$2/$3");

日付としての妥当性も必要なら、DateTime.TryParseExactで解析したうえでToStringにより出力形式を指定します。

7-8. ファイル名に使用できない文字を置換する

実行環境でファイル名に使用できない文字は、Path.GetInvalidFileNameCharsで取得できます。

using System.IO;using System.Text.RegularExpressions;

string fileName = "売上:2026/06/20?.csv";

string pattern =$"[{Regex.Escape(new string(Path.GetInvalidFileNameChars()))}]";

string safeFileName = Regex.Replace(fileName,pattern,"_");

Console.WriteLine(safeFileName);

無効な文字はOSによって異なる可能性があります。そのため、禁止文字を固定で列挙するより、Path.GetInvalidFileNameCharsを使用するほうが安全です。

ただし、予約名、末尾のピリオドやスペース、最大パス長などは別途考慮が必要です。

7-9. CSV内の文字列を置換する

CSVの単純な値を置換するだけなら、通常のReplaceを使用できます。

string csv = "商品名,状態\n商品A,未処理\n商品B,未処理";

string result = csv.Replace("未処理", "処理済み");

Console.WriteLine(result);

ただし、CSVには引用符、フィールド内のカンマ、フィールド内改行、引用符のエスケープといった規則があります。

例えば、次のCSVをカンマのReplaceだけで処理すると、フィールド内のカンマまで変更してしまいます。

1,"東京都新宿区,西新宿",1000

列単位で安全に処理する必要がある場合は、CSVパーサーを使って読み込み、対象フィールドだけを変更してから書き出してください。

7-10. URLやパスの区切り文字を置換する

Windows形式のパス区切り文字をスラッシュへ変更する例です。

string path = @"C:\work\data\sample.txt";string result = path.Replace('\', '/');

Console.WriteLine(result); // C:/work/data/sample.txt

通常文字列でバックスラッシュを表す場合は、\と記述します。

string result = path.Replace("\", "/");

URLを処理する場合、文字列全体を単純に置換すると、https://などの構造を壊す可能性があります。URLの構成要素を変更する場合は、UriUriBuilderを利用するほうが安全です。

ファイルパスの結合には、区切り文字を手作業で置換するよりPath.Combineを使用します。

string path = Path.Combine("data", "images", "sample.png");

7-11. 個人情報の一部をマスキングする

電話番号の中央部分をマスキングする例です。

string phone = "090-1234-5678";

string masked = Regex.Replace(phone,@"^(\d{2,4})-(\d{2,4})-(\d{4})$","$1-****-$3");

Console.WriteLine(masked); // 090-****-5678

メールアドレスのローカル部を一部隠す例です。

string email = "taro.yamada@example.com";

string masked = Regex.Replace(email,@"^(.{2}).(@.+)$","$1**$2");

Console.WriteLine(masked); // ta***@example.com

個人情報の形式は多様です。マスキング処理では、入力形式が想定外だった場合に元データがそのまま表示されない設計も重要です。

8. ReplaceとRegex.Replaceの違いと使い分け

8-1. 固定文字列の置換にはString.Replaceを使う

置換対象が固定されている場合は、String.Replaceが適しています。

string result = text.Replace("旧名称", "新名称");

String.Replaceには次の利点があります。

  • コードが短く読みやすい

  • 正規表現の知識が不要

  • パターンのエスケープを考える必要がない

  • 一般に正規表現より処理の負担が小さい

単純な置換で正規表現を使用すると、コードの意図が分かりにくくなる可能性があります。

8-2. パターンに一致する文字列の置換にはRegex.Replaceを使う

置換対象が一定のパターンで表される場合は、Regex.Replaceが適しています。

string result = Regex.Replace(text, @"\d+", "[数値]");

例えば、次の処理に向いています。

  • 桁数が異なる数字を置換する

  • 複数種類の空白や改行をまとめる

  • 日付や電話番号の形式を変換する

  • 一致部分をキャプチャして並べ替える

  • 大文字・小文字を無視して置換する

固定文字列で実現できる処理に正規表現を使う必要はありません。

8-3. 処理速度とメモリ使用量の違い

一般に、固定文字列の置換ではString.Replaceのほうが単純で、正規表現エンジンを使用するRegex.Replaceより負担を抑えやすくなります。

ただし、実際の性能は次の条件によって変わります。

  • 入力文字列の長さ

  • 置換対象の数

  • 正規表現パターンの複雑さ

  • 一致回数

  • メソッドの呼び出し回数

  • .NETのバージョン

  • 正規表現インスタンスの再利用方法

性能が重要な処理では、推測だけで決めず、実際のデータに近い条件でベンチマークを実施しましょう。

8-4. 可読性と保守性の違い

String.Replaceは処理内容を直感的に理解できます。

text.Replace("未処理", "完了");

正規表現は複雑な処理を短く書ける反面、パターンが読みにくくなることがあります。

Regex.Replace(text, @"(?<=\D)\d+(?=\D)", "");

複雑な正規表現を使用する場合は、次の工夫が有効です。

  • パターンへ意味のある変数名を付ける

  • コメントで目的を説明する

  • 名前付きキャプチャを使用する

  • RegexOptions.IgnorePatternWhitespaceで整形する

  • テストコードを用意する

短さだけでなく、将来の変更やレビューのしやすさも考慮しましょう。

8-5. 複数条件を置換するときの選び方

少数の固定文字列を置換する場合は、Replaceの連続呼び出しで十分です。

string result = text.Replace("赤", "R").Replace("青", "B").Replace("緑", "G");

「赤、青、緑のいずれかを同じ文字へ置換する」場合は、正規表現でまとめられます。

string result = Regex.Replace(text,"赤|青|緑","");

置換後の値がそれぞれ異なる場合は、辞書とMatchEvaluatorを組み合わせる方法があります。

var map = new Dictionary<string, string>{["赤"] = "Red",["青"] = "Blue",["緑"] = "Green"};

string result = Regex.Replace(text,"赤|青|緑",match => map[match.Value]);

8-6. 大量データを置換するときの注意点

stringは変更できないため、置換のたびに新しい文字列が生成されます。多数のReplaceを連続して実行すると、中間文字列が多く作られる可能性があります。

大量データを扱う場合は、次の点を検討します。

  • 不要な置換処理を減らす

  • 複数条件を1回の正規表現へまとめる

  • 同じRegexを再利用する

  • StringBuilder.Replaceを利用する

  • ストリーム単位や行単位で処理する

  • 実データを使って性能を測定する

巨大なファイルを一度に文字列へ読み込むと、置換以前に大きなメモリを消費します。必要に応じてStreamReaderで行単位に処理してください。

9. C#の文字列置換ができない・効かない原因

9-1. Replaceの戻り値を変数に代入していない

最も多い原因は、戻り値を受け取っていないことです。

string text = "Hello C#";text.Replace("C#", "World");

Console.WriteLine(text); // Hello C#

次のように代入します。

text = text.Replace("C#", "World");

stringはイミュータブルであり、Replaceは元の文字列を直接変更しません。

9-2. 大文字・小文字が一致していない

通常の置換では、大文字と小文字が区別されます。

string text = "Hello";string result = text.Replace("hello", "Hi");

Console.WriteLine(result); // Hello

大文字・小文字を無視する場合は、StringComparison.OrdinalIgnoreCaseを指定します。

string result = text.Replace("hello","Hi",StringComparison.OrdinalIgnoreCase);

またはRegexOptions.IgnoreCaseを使用します。

9-3. 全角文字と半角文字が混在している

見た目が似ていても、全角と半角は異なる文字です。

string text = "商品A";string result = text.Replace("A", "B");

Console.WriteLine(result); // 商品A

文字列中のは全角であり、半角のAとは一致しません。

必要に応じて、入力時に文字種を統一します。

using System.Text;

string normalized = text.Normalize(NormalizationForm.FormKC);

ただし、互換正規化では英数字以外の文字も変化する場合があります。対象データへの影響を確認して使用してください。

9-4. 改行コードが想定と異なっている

\r\nを置換しても、入力が\nだけなら一致しません。

string text = "1行目\n2行目";string result = text.Replace("\r\n", " ");

複数種類の改行を処理する場合は、次のように記述します。

string result = Regex.Replace(text,@"\r\n?|\n"," ");

デバッグ時には、改行を可視化すると原因を確認しやすくなります。

string visible = text.Replace("\r", "\r").Replace("\n", "\n");

Console.WriteLine(visible);

9-5. バックスラッシュなどのエスケープが正しくない

通常の文字列リテラルでは、バックスラッシュはエスケープ文字として扱われます。

string path = "C:\data\sample.txt";

逐語的文字列リテラルを使用すれば、バックスラッシュをそのまま書けます。

string path = @"C:\data\sample.txt";

バックスラッシュを置換する例は次のとおりです。

string result = path.Replace("\", "/");

またはchar型で指定します。

string result = path.Replace('\', '/');

9-6. 正規表現の特殊文字をエスケープしていない

正規表現では、ピリオドや括弧、プラスなどに特別な意味があります。

string text = "example.com";string result = Regex.Replace(text, ".", "");

.は任意の1文字を表すため、文字列全体が置換対象になります。

ピリオドそのものへ一致させるには、エスケープします。

string result = Regex.Replace(text, @".", "");// example_com

検索文字列を変数で受け取る場合は、Regex.Escapeを使用します。

string keyword = "example.com";string pattern = Regex.Escape(keyword);

string result = Regex.Replace(text, pattern, "sample.jp");

9-7. 置換する順番によって結果が変わっている

置換条件によっては、処理順序で結果が変わります。

string text = "abc";

string result = text.Replace("a", "ab").Replace("ab", "X");

Console.WriteLine(result); // Xbc

順番を逆にすると結果が異なります。

string result = text.Replace("ab", "X").Replace("a", "ab");

Console.WriteLine(result); // Xc

置換後の文字列が、次の置換条件に一致する場合は特に注意が必要です。

必要であれば、正規表現と辞書を組み合わせ、元の文字列に対して1回で置換します。

9-8. nullや空文字を正しく処理していない

対象文字列がnullの場合、インスタンスメソッドのReplaceは呼び出せません。

string? text = null;string result = text.Replace("A", "B"); // 例外

事前に確認します。

string? text = null;

string result = string.IsNullOrEmpty(text)? string.Empty: text.Replace("A", "B");

null条件演算子を使用する方法もあります。

string? result = text?.Replace("A", "B");

また、String.Replaceの置換前文字列に空文字を指定すると例外が発生します。

text.Replace("", "A");

置換条件が外部入力の場合は、空文字でないことを確認してください。

9-9. Regex.Replaceで意図しない範囲まで一致している

正規表現の.は、可能な限り長く一致する貪欲なパターンです。

string text = "<b>1</b><b>2</b>";string result = Regex.Replace(text, "<b>.</b>", "");

Console.WriteLine(result); // 空文字

最初の<b>から最後の</b>まで一致するためです。

最短一致にするには.?を使用します。

string result = Regex.Replace(text,"<b>.?</b>","");

ただし、正規表現だけで複雑なHTMLを処理する方法には限界があります。対象データの構造に適したパーサーを使用することも検討してください。

10. 安全かつ効率的に文字列を置換するポイント

10-1. null・空文字を事前に確認する

外部入力を置換する場合は、nullや空文字を考慮します。

static string ReplaceSafe(string? input,string oldValue,string newValue){if (string.IsNullOrEmpty(input)){return input ?? string.Empty;}

if (string.IsNullOrEmpty(oldValue)){return input;}return input.Replace(oldValue, newValue);

}

空白だけの入力も無効として扱う場合は、IsNullOrWhiteSpaceを使用します。

if (string.IsNullOrWhiteSpace(input)){return string.Empty;}

どの状態を有効とするかは、アプリケーションの仕様に合わせて決めましょう。

10-2. ユーザー入力はRegex.Escapeでエスケープする

ユーザーが入力した文字列を正規表現パターンとして直接連結すると、特殊文字が正規表現として解釈されます。

string keyword = userInput;string result = Regex.Replace(text, keyword, "置換後");

固定文字列として検索したい場合は、Regex.Escapeを使用します。

string keyword = userInput;string pattern = Regex.Escape(keyword);

string result = Regex.Replace(text,pattern,"置換後");

置換後の文字列にもユーザー入力を使用する場合、$1$&などが置換パターンとして解釈される点に注意が必要です。文字列をそのまま返したい場合は、MatchEvaluatorを使用すると安全です。

string replacement = userReplacement;

string result = Regex.Replace(text,Regex.Escape(userKeyword),_ => replacement);

10-3. 正規表現にタイムアウトを設定する

複雑な正規表現や悪意のある入力では、正規表現の評価に非常に長い時間がかかることがあります。

外部入力を処理する場合は、タイムアウトを設定します。

using System.Text.RegularExpressions;

try{string result = Regex.Replace(input,pattern,replacement,RegexOptions.None,TimeSpan.FromSeconds(1));}catch (RegexMatchTimeoutException){Console.WriteLine("正規表現の処理がタイムアウトしました。");}

タイムアウト時間は、入力サイズやシステム要件に合わせて設定してください。

10-4. 同じ正規表現を繰り返し使う場合は再利用する

同じパターンを何度も使う場合は、Regexインスタンスを再利用すると、コードを整理しやすくなります。

private static readonly Regex NumberRegex = new(@"\d+",RegexOptions.CultureInvariant,TimeSpan.FromSeconds(1));

static string MaskNumbers(string input){return NumberRegex.Replace(input, "*");}

用途によってはRegexOptions.Compiledも選択肢になります。

private static readonly Regex NumberRegex = new(@"\d+",RegexOptions.Compiled | RegexOptions.CultureInvariant,TimeSpan.FromSeconds(1));

ただし、コンパイルにもコストがあるため、使用頻度の低い正規表現へ無条件に指定すれば必ず高速になるわけではありません。

10-5. GeneratedRegexを活用して正規表現を最適化する

.NET 7以降では、GeneratedRegex属性を使ってコンパイル時に正規表現のコードを生成できます。

using System.Text.RegularExpressions;

public static partial class TextReplacer{[GeneratedRegex(@"\s+",RegexOptions.CultureInvariant,matchTimeoutMilliseconds: 1000)]private static partial Regex WhiteSpaceRegex();

public static string NormalizeSpaces(string input){return WhiteSpaceRegex().Replace(input, " ");}

}

使用例は次のとおりです。

string result = TextReplacer.NormalizeSpaces("C#   文字列\t置換");

Console.WriteLine(result); // C# 文字列 置換

GeneratedRegexには、正規表現を静的に解析できる、起動時の処理を抑えられる、AOT環境と相性がよいといった利点があります。

属性を使用するメソッドと、それを含む型にはpartialが必要です。

10-6. 大量の置換ではStringBuilderの利用を検討する

多数の固定文字列を繰り返し置換する場合は、StringBuilderの利用を検討できます。

using System.Text;

var builder = new StringBuilder("赤、青、緑、赤");

builder.Replace("赤", "Red").Replace("青", "Blue").Replace("緑", "Green");

string result = builder.ToString();

Console.WriteLine(result);

StringBuilderは内部の文字列バッファーを変更できるため、文字列の連結や編集を大量に繰り返す処理で有効です。

ただし、短い文字列や置換回数が少ない処理では、通常のString.Replaceのほうが簡潔です。性能上の効果は実際の条件で測定してください。

10-7. 置換結果をテストコードで検証する

文字列置換では、空文字、改行、全角文字、想定外の形式などによる不具合が発生しやすいため、テストコードで確認します。

xUnitを使用した例は次のとおりです。

using Xunit;

public class TextReplaceTests{[Fact]public void Hyphenをスラッシュへ置換できる(){string input = "2026-06-20";

    string actual = input.Replace("-", "/");Assert.Equal("2026/06/20", actual);}<span data-placeholder-token="true" class="text-token-text-primary cursor-text rounded-sm" style="background-color: color-mix(in srgb, var(--theme-user-selection-bg, var(--selection)) 30%, transparent); padding-top: 4px; padding-bottom: 4px;">[Theory]</span><span data-placeholder-token="true" class="text-token-text-primary cursor-text rounded-sm" style="background-color: color-mix(in srgb, var(--theme-user-selection-bg, var(--selection)) 30%, transparent); padding-top: 4px; padding-bottom: 4px;">[InlineData("03-1234-5678", "0312345678")]</span><span data-placeholder-token="true" class="text-token-text-primary cursor-text rounded-sm" style="background-color: color-mix(in srgb, var(--theme-user-selection-bg, var(--selection)) 30%, transparent); padding-top: 4px; padding-bottom: 4px;">[InlineData("(03)1234-5678", "0312345678")]</span><span data-placeholder-token="true" class="text-token-text-primary cursor-text rounded-sm" style="background-color: color-mix(in srgb, var(--theme-user-selection-bg, var(--selection)) 30%, transparent); padding-top: 4px; padding-bottom: 4px;">[InlineData("03 1234 5678", "0312345678")]</span>public void 電話番号から数字以外を削除できる(string input,string expected){string actual = Regex.Replace(input,@"<span data-placeholder-token="true" class="text-token-text-primary cursor-text rounded-sm" style="background-color: color-mix(in srgb, var(--theme-user-selection-bg, var(--selection)) 30%, transparent); padding-top: 4px; padding-bottom: 4px;">[^0-9]</span>","");Assert.Equal(expected, actual);}

}

少なくとも次のパターンをテストすると安心です。

  • 通常の入力

  • 一致する文字列がない入力

  • 複数箇所に一致する入力

  • 空文字

  • null

  • 全角文字を含む入力

  • 異なる改行コード

  • 正規表現の境界条件

  • 非常に長い入力

  • 想定外の形式

まとめ

C#で固定された文字や文字列を置換する場合は、String.Replaceを使用します。

string result = text.Replace("置換前", "置換後");

対象文字列を削除する場合は、空文字へ置換します。

string result = text.Replace("削除対象", "");

数字、空白、改行、日付形式など、一定のパターンに一致する部分を置換する場合は、Regex.Replaceが適しています。

string result = Regex.Replace(text,@"\d+","[数値]");

C#の文字列置換では、次の点が特に重要です。

  • Replaceの戻り値を必ず受け取る

  • 固定文字列にはString.Replaceを使う

  • パターン検索にはRegex.Replaceを使う

  • 削除では空文字へ置換する

  • 改行コードの違いを考慮する

  • 大文字・小文字や全角・半角の違いを確認する

  • ユーザー入力はRegex.Escapeで処理する

  • 外部入力を扱う正規表現にはタイムアウトを設定する

  • 複雑な置換はテストコードで検証する

単純な処理に正規表現を使いすぎず、目的に応じてReplaceRegex.ReplaceRemoveTrimを使い分けることが、安全で読みやすいコードにつながります。