C#で連続する空白を1つにする方法
C#で業務システムやWebアプリケーションを開発していると、文字列の中に複数の空白が連続して含まれていることがあります。
たとえば、ユーザーが名前や検索キーワードを入力するときに、誤ってスペースを何度も入力してしまうケースです。
// 空白が連続している文字列
string text = "C# プログラミング 入門";C#このような文字列を、そのまま検索処理やデータ登録処理に渡すと、不要な空白によって文字列の比較や表示が意図どおりにならない場合があります。
そこで利用するのが、連続する空白を1つにまとめる処理です。
C#では、正規表現を利用することで、この処理を簡潔に実装できます。
using System.Text.RegularExpressions;
string text = "C# プログラミング 入門";
// 連続する空白文字を1つの半角スペースにまとめる
string result = Regex.Replace(text, @"\s+", " ");
Console.WriteLine(result);C#実行結果は次のようになります。
C# プログラミング 入門
この処理では、連続していた空白が1つの半角スペースに置き換えられています。
ただし、実務では「半角スペースだけを対象にするのか」「タブや改行も対象にするのか」「文字列の先頭と末尾にある空白も削除するのか」といった仕様を明確にする必要があります。
この記事では、基本的な書き方から正規表現の仕組み、実務で使えるテンプレート、nullへの対応、注意点まで、順番に解説します。
連続する空白を1つにするとは
まず、どのような処理を実現したいのかを整理しましょう。
たとえば、次の文字列があるとします。
string text = "C# 入門";C#「C#」と「入門」の間には、5つの半角スペースが含まれています。
この空白を1つにすると、次のようになります。
C# 入門
同じように、次のような文字列も考えられます。
// 空白が連続している文字列
string text = "東京 大阪 名古屋";C#これを整形すると、次のようになります。
東京 大阪 名古屋
このように、複数の空白を1つにまとめることで、文字列の見た目や形式を統一できます。
Trimとは役割が異なる
ここで、これまでに学んだTrim()との違いを理解しておきましょう。
Trim()は、文字列の先頭と末尾にある空白文字を取り除くメソッドです。一方、連続する空白を1つにまとめる処理は、文字列の途中にある空白も対象にします。
| 処理 | 処理前 | 処理後 |
|---|---|---|
| Trim() | " C# 入門 " | "C# 入門" |
| 連続する空白を1つにする | "C# 入門" | "C# 入門" |
| Trim()と空白の集約 | " C# 入門 " | "C# 入門" |
Trim()だけでは、文字列の途中にある複数の空白はそのまま残ります。
そのため、前後の空白を削除する処理と、連続する空白を1つにする処理は、必要に応じて組み合わせて利用します。
方法1:Regex.Replace()を使う
C#で連続する空白を1つにまとめる方法として、まず覚えておきたいのがRegex.Replace()です。
Regexは正規表現を扱うためのクラスで、文字列の中から特定のパターンを探し、別の文字列に置き換える処理を行えます。
基本的なコード
次のコードを見てみましょう。
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
string text = "C# プログラミング 入門";
// 連続する空白文字を半角スペース1つに置き換える
string result = Regex.Replace(text, @"\s+", " ");
// 整形後の文字列を表示する
Console.WriteLine(result);
}
}C#実行結果は次のとおりです。
C# プログラミング 入門
このコードでは、Regex.Replace()によって連続する空白文字を探し、半角スペース1つに置き換えています。
Regex.Replace()の書式
基本的な書式は次のとおりです。
Regex.Replace(対象の文字列, 検索パターン, 置換後の文字列);C#それぞれの引数の役割を確認しましょう。
| 引数 | 役割 | 例 |
|---|---|---|
| 対象の文字列 | 処理する文字列 | text |
| 検索パターン | 置き換えたい文字列の条件 | @"\s+" |
| 置換後の文字列 | 見つかった部分を何に置き換えるか | " " |
今回のコードを分解すると、次のようになります。
// 処理対象の文字列
string text = "C# 入門";
// 検索パターン:空白文字が1文字以上連続する部分
string pattern = @"\s+";
// 置換後の文字列:半角スペース1つ
string replacement = " ";
// 連続する空白を1つにまとめる
string result = Regex.Replace(text, pattern, replacement);C#処理を変数に分けて書くと、正規表現に慣れていない初心者の方でも、それぞれの役割を理解しやすくなります。
正規表現「\s+」の意味
今回の処理で重要なのが、正規表現の\s+です。
正規表現とは、文字列の特徴やパターンを表現するための記法です。
たとえば、「数字が連続する部分」や「英字だけの部分」など、文字列に含まれる特定のパターンを指定できます。
「\s」は空白文字を表す
正規表現における\sは、空白文字に一致するパターンです。
一般的には、次のような文字が対象になります。
- 半角スペース
- タブ
- 改行
- その他、正規表現エンジンが空白文字として扱う文字
たとえば、次の文字列には、半角スペース、タブ、改行が含まれています。
// タブと改行を含む文字列
string text = "C# \t プログラミング\n 入門";C#\sを使えば、半角スペースだけでなく、タブや改行なども空白文字としてまとめて処理できます。
「+」は1回以上の繰り返しを表す
正規表現の+は、直前のパターンが1回以上繰り返されることを表します。
そのため、\s+は「空白文字が1文字以上連続している部分」という意味になります。
| パターン | 意味 |
|---|---|
\s | 空白文字1文字 |
\s+ | 空白文字が1文字以上連続する部分 |
\s* | 空白文字が0文字以上連続する部分 |
今回の目的は、空白が1つの場合も、5つの場合も、タブが複数ある場合も、まとめて1つの半角スペースに置き換えることです。
そのため、\s+を使います。
「\s*」ではなく「\s+」を使う理由
初心者の方が注意したいのは、\s*と\s+の違いです。
\s*は空白が0文字でも一致するため、空白が存在しない場所にも一致する可能性があります。今回のように、連続する空白だけを置き換えたい場合には、\s+を使うほうが意図に合っています。
正規表現では、記号を1つ変えるだけで処理の意味が変わります。検索パターンは、その目的に合ったものを選ぶことが大切です。
方法2:半角スペースだけを1つにする
業務によっては、タブや改行などを対象にせず、半角スペースだけを1つにまとめたい場合があります。
その場合は、正規表現を +にします。
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
string text = "C# プログラミング 入門";
// 連続する半角スペースだけを1つにまとめる
string result = Regex.Replace(text, @" +", " ");
Console.WriteLine(result);
}
}C#実行結果は次のとおりです。
C# プログラミング 入門
+は、半角スペースが1文字以上連続する部分に一致します。
「\s+」と「 +」の違い
| 正規表現 | 主な対象 | 向いている用途 |
|---|---|---|
\s+ | 半角スペース、タブ、改行などの空白文字 | さまざまな空白をまとめて整形する |
+ | 半角スペース | 半角スペースだけを整形する |
どちらを選ぶべきかは、データの仕様によって異なります。
たとえば、ユーザーが入力した検索キーワードの空白をまとめたいなら\s+が便利です。一方、文章の中にある改行を維持したいなら、\s+で改行まで置き換えることが意図しない結果につながる場合があります。
「空白をまとめる」といっても、どの文字を空白として扱うのかを先に決めることが重要です。
前後の空白も同時に削除する
連続する空白を1つにまとめるだけでは、文字列の先頭や末尾に空白が残ることがあります。
たとえば、次の文字列です。
string text = " C# 入門 ";C#これにRegex.Replace(text, @"\s+", " ")を実行すると、空白の連続は1つになりますが、先頭と末尾には半角スペースが残ります。
C# 入門
前後の空白も削除したい場合は、Trim()を組み合わせます。
using System.Text.RegularExpressions;
string text = " C# 入門 ";
// 1. 連続する空白文字を半角スペース1つにまとめる
string result = Regex.Replace(text, @"\s+", " ");
// 2. 先頭と末尾の空白を削除する
result = result.Trim();
Console.WriteLine(result);C#実行結果は次のとおりです。
C# 入門
このように、正規表現による空白の集約とTrim()による前後の空白削除を組み合わせると、文字列を扱いやすい形式に整えられます。
実務テンプレート1:文字列を整形するメソッドを作る
同じ処理を複数の場所で利用する場合は、専用のメソッドにまとめると便利です。
ここでは、連続する空白を1つにまとめ、前後の空白も削除するメソッドを作ります。
using System.Text.RegularExpressions;
public static class StringUtility
{
/// <summary>
/// 連続する空白文字を1つの半角スペースにまとめ、
/// 文字列の前後の空白を削除します。
/// nullの場合は空文字を返します。
/// </summary>
public static string NormalizeWhitespace(string? value)
{
// nullの場合は空文字を返す
if (value == null)
{
return "";
}
// 連続する空白文字を半角スペース1つに置き換える
string result = Regex.Replace(value, @"\s+", " ");
// 先頭と末尾の空白を削除する
return result.Trim();
}
}C#このメソッドは、次の3つの処理を行います。
- nullの場合は空文字を返します。
- 連続する空白文字を半角スペース1つにまとめます。
- 文字列の先頭と末尾に残った空白を削除します。
ユーティリティの使用例
string text = " C# プログラミング \t 入門 ";
// 空白を整形するユーティリティを利用する
string result = StringUtility.NormalizeWhitespace(text);
// 整形後の文字列を表示する
Console.WriteLine(result);C#結果は次のようになります。
C# プログラミング 入門
共通メソッドにしておけば、フォーム入力、検索キーワード、表示用の文字列など、同じルールで整形したい場面から利用できます。
ただし、文字列の種類によっては空白や改行を維持する必要があります。すべての文字列に無条件で適用するのではなく、対象のデータを決めて利用しましょう。
実務テンプレート2:検索キーワードの空白を整える
Webサイトや業務アプリケーションの検索フォームでは、入力されたキーワードを整形すると便利な場合があります。
たとえば、ユーザーが次のように入力したとします。
C# 入門
前後の空白を削除し、連続する空白を1つにすると、検索キーワードを統一できます。
using System.Text.RegularExpressions;
string? input = GetSearchKeyword();
// nullの場合は空文字、それ以外は空白を整形する
string keyword = input == null
? ""
: Regex.Replace(input, @"\s+", " ").Trim();
// 未入力なら検索しない
if (keyword.Length == 0)
{
Console.WriteLine("検索キーワードを入力してください。");
return;
}
// 整形済みのキーワードを検索処理へ渡す
Search(keyword);C#このコードでは、nullを空文字に変換したうえで、空白の集約と前後の空白削除を行っています。
なお、GetSearchKeyword()とSearch()は説明用のメソッド名です。実際のアプリケーションでは、使用しているフォームや検索処理に合わせて置き換えてください。
空白を整形しても検索結果が必ず一致するとは限らない
検索キーワードの空白を整形することで、入力形式の違いを減らせます。
しかし、空白を整形しただけで、全角・半角の違い、大文字・小文字の違い、文字の表記揺れなどがすべて解消されるわけではありません。
検索対象のデータやデータベースの照合順序などによっても検索結果は変わるため、空白の整形と文字列比較の仕様は分けて設計しましょう。
実務テンプレート3:半角スペースだけを整形するユーティリティ
タブや改行を残したい場合には、半角スペースだけを対象にしたメソッドを作る方法があります。
using System.Text.RegularExpressions;
public static class StringUtility
{
/// <summary>
/// 連続する半角スペースを1つにまとめます。
/// タブや改行は対象にしません。
/// nullの場合は空文字を返します。
/// </summary>
public static string NormalizeSpaces(string? value)
{
// nullの場合は空文字を返す
if (value == null)
{
return "";
}
// 連続する半角スペースを1つにまとめる
return Regex.Replace(value, @" +", " ");
}
}C#このメソッドでは、半角スペースだけを対象にしています。そのため、タブや改行は空白の集約対象になりません。
ただし、文字列の先頭や末尾にある半角スペースも1つにまとめられるだけで、削除されるわけではありません。前後の空白も削除したい場合は、目的に合わせてTrim()を組み合わせてください。
Regex.Replace()を使うときの注意点
注意点1:文字列の改行まで置き換わることがある
\s+は改行も対象にするため、文章の整形に使うと、改行が半角スペースに置き換わることがあります。
string text = "1行目\n2行目";
// 改行も空白文字として置き換えられる
string result = Regex.Replace(text, @"\s+", " ");
Console.WriteLine(result);C#結果は次のようになります。
1行目 2行目
元の改行は残りません。
複数行の文章やログなど、改行が意味を持つデータでは注意が必要です。改行を維持したい場合は、\s+ではなく、対象を半角スペースなどに限定したパターンを選びます。
注意点2:すべての空白を同じ意味として扱ってよいとは限らない
空白文字には、半角スペース、タブ、改行などがあります。
これらをすべて半角スペースに統一することが、常に正しいとは限りません。
たとえば、表形式のテキストや、タブ区切りデータ、ソースコード、ログファイルなどでは、空白や改行がデータの構造を表している場合があります。
このようなデータに空白の集約処理を行うと、元の構造を壊してしまう可能性があります。
空白を整形する前に、その空白が単なる見た目の問題なのか、データの意味を持っているのかを確認することが重要です。
注意点3:Regex.Replace()は元の文字列を直接変更しない
C#のstringは不変の型です。Regex.Replace()は元の文字列を書き換えるのではなく、置き換え後の新しい文字列を返します。
string text = "C# 入門";
// 戻り値を受け取っていないため、textは変わらない
Regex.Replace(text, @"\s+", " ");
Console.WriteLine(text);C#このコードでは、textに連続する空白が残ったままです。
結果を利用するには、次のように代入します。
string text = "C# 入門";
// 置き換え後の文字列を再代入する
text = Regex.Replace(text, @"\s+", " ");
Console.WriteLine(text);C#注意点4:正規表現は目的に合わせて使い分ける
正規表現は非常に便利ですが、必要以上に複雑なパターンを作ると、コードが読みにくくなることがあります。
連続する空白を1つにするだけなら、基本的には次のコードで十分です。
// 空白文字の連続を半角スペース1つにまとめる
string result = Regex.Replace(text, @"\s+", " ");C#半角スペースだけを対象にしたいなら、次のコードを使います。
// 半角スペースの連続だけを1つにまとめる
string result = Regex.Replace(text, @" +", " ");C#このように、目的が明確なシンプルなパターンを選ぶことが、保守しやすいコードにつながります。
セキュリティ上の注意点
空白の集約は文字列を整形するための処理であり、それだけで入力値が安全になるわけではありません。
たとえば、ユーザーが入力した文字列をSQL文へ連結する場合、空白を整形してもSQLインジェクション対策にはなりません。
// 注意:入力値をSQL文に直接連結する方法は避ける
string sql = "SELECT * FROM Users WHERE Name = '" + keyword + "'";C#データベースへ値を渡す場合は、パラメータ化クエリなど、利用しているデータアクセス技術に適した安全な方法を使用してください。
また、HTMLへ文字列を出力する場合も、出力先に応じた適切なエンコードが必要です。
空白の整形、入力値の検証、SQLインジェクション対策、HTML出力時のエンコードは、それぞれ目的の異なる処理として設計しましょう。
大量の文字列を処理する場合
通常のフォーム入力や検索キーワードであれば、Regex.Replace()を使う方法で十分な場合が多いです。
一方、大量の文字列を繰り返し処理する場合には、パフォーマンスも考慮します。
たとえば、同じ正規表現を大量のデータに対して繰り返し使う場合は、Regexインスタンスを再利用する設計や、対象の.NETバージョンで利用できる最適化機能を検討できます。
ただし、最初から複雑な最適化を行う必要はありません。まずは正しく動作するコードを作り、実際に処理時間が問題になった場合に計測して改善することをおすすめします。
動作確認用のサンプルコード
ここまでの内容をまとめて確認できるサンプルです。
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
// 半角スペースが連続している文字列
string text1 = " C# プログラミング 入門 ";
// タブや改行を含む文字列
string text2 = "東京\t\t大阪\n\n名古屋";
// 1. 空白文字の連続を半角スペース1つにまとめる
string result1 = Regex.Replace(text1, @"\s+", " ");
// 2. 先頭と末尾の空白を削除する
result1 = result1.Trim();
// 3. タブや改行も半角スペース1つにまとめる
string result2 = Regex.Replace(text2, @"\s+", " ");
// 結果を表示する
Console.WriteLine(result1);
Console.WriteLine(result2);
}
}C#実行結果は次のようになります。
C# プログラミング 入門
東京 大阪 名古屋
このサンプルでは、連続する空白文字の集約と、前後の空白削除を組み合わせています。
よくある質問
連続する空白を1つにするには、Trim()だけで十分ですか?
いいえ。Trim()は文字列の先頭と末尾にある空白を削除するメソッドです。文字列の途中にある連続した空白を1つにまとめるには、Regex.Replace()などを利用します。
半角スペースだけを対象にするにはどうすればよいですか?
正規表現に +を指定します。
// 連続する半角スペースだけを1つにまとめる
string result = Regex.Replace(text, @" +", " ");C#タブや改行もまとめたい場合はどうすればよいですか?
\s+を利用します。ただし、改行も半角スペースに置き換えられるため、改行を維持する必要がある文章やデータには注意してください。
nullが渡された場合はどうすればよいですか?
Regex.Replace()にnullをそのまま渡さず、先にnullを確認します。nullなら空文字にする仕様であれば、次のように書けます。
string? input = GetInput();
// nullなら空文字、それ以外なら空白を集約して前後を削除
string result = input == null
? ""
: Regex.Replace(input, @"\s+", " ").Trim();C#空白を集約すると文字列の意味が変わることはありますか?
あります。文章の改行、タブ区切りデータ、ソースコードなどでは、空白が意味を持っている場合があります。処理対象のデータに合わせて、空白を集約してよいか確認してください。
まとめ
C#で連続する空白を1つにまとめるには、Regex.Replace()と正規表現を利用する方法が便利です。
基本となるコードは次のとおりです。
using System.Text.RegularExpressions;
string text = "C# プログラミング 入門";
// 連続する空白文字を半角スペース1つにまとめる
string result = Regex.Replace(text, @"\s+", " ");C#前後の空白も削除する場合は、Trim()を組み合わせます。
using System.Text.RegularExpressions;
string text = " C# プログラミング 入門 ";
// 1. 連続する空白文字を1つにまとめる
string result = Regex.Replace(text, @"\s+", " ");
// 2. 先頭と末尾の空白を削除する
result = result.Trim();C#また、半角スペースだけを対象にする場合は、次のパターンを使います。
// 半角スペースの連続だけを1つにまとめる
string result = Regex.Replace(text, @" +", " ");C#最後に、実務で覚えておきたいポイントを整理します。
Regex.Replace(text, @"\s+", " ")は、空白文字の連続を半角スペース1つにまとめます。Regex.Replace(text, @" +", " ")は、連続する半角スペースだけを対象にします。- 前後の空白も削除したい場合はTrim()を組み合わせます。
- Regex.Replace()は元の文字列を直接変更しないため、戻り値を利用します。
\s+はタブや改行も対象にするため、文章や構造化データでは注意が必要です。- nullの可能性がある入力値は、処理前に確認します。
- 空白の整形だけで、入力値の検証やセキュリティ対策が完了するわけではありません。
連続する空白を1つにまとめる処理は、検索キーワードの整形、入力値の正規化、文字列の表示調整など、さまざまな業務で役立ちます。
ただし、重要なのは単に空白を削除することではありません。どの空白を対象にするのか、改行を維持する必要があるのか、整形後の値をどのように利用するのかを明確にしたうえで実装することが、保守しやすく安全なC#コードにつながります。

