閉じる

C#のSplitで複数の区切り文字を指定する方法!文字列や正規表現も解説

C#でプログラミングを行う際、文字列を特定のルールに基づいて分割する処理は、データ解析やファイル処理において避けては通れない非常に重要な操作です。

単純なカンマ区切りであれば容易ですが、実務では「カンマ、セミコロン、スペースが混在している」といった複雑な状況に直面することも少なくありません。

本記事では、C#のstring.Splitメソッドを使いこなし、複数の区切り文字や文字列、さらには正規表現を用いて柔軟に文字列を分割するテクニックを詳しく解説します。

最新の.NETにおける便利なオプションについても触れていきますので、ぜひ最後までご覧ください。

複数の文字(char)を区切り文字として指定する基本

C#のstring.Splitメソッドは、引数として文字の配列(char[])を受け取ることができます。

これにより、一度の呼び出しで複数の異なる文字を区切りとして認識させることが可能です。

char配列を利用した分割のコード例

最も標準的で利用頻度が高いのが、char型の配列を渡す方法です。

以下のサンプルコードでは、カンマ、セミコロン、スラッシュの3種類を区切り文字として指定しています。

C#
using System;

class Program
{
    static void Main()
    {
        // 分割対象の文字列
        string source = "C#,Java;Python/PHP";

        // 区切り文字をchar配列として定義
        char[] separators = new char[] { ',', ';', '/' };

        // Splitメソッドで分割
        string[] languages = source.Split(separators);

        // 結果の出力
        Console.WriteLine("--- 分割結果 ---");
        foreach (string lang in languages)
        {
            Console.WriteLine(lang);
        }
    }
}
実行結果
--- 分割結果 ---
C#
Java
Python
PHP

複数の文字を指定する際のポイント

C#のSplitメソッドは、可変長引数(params)に対応しているため、配列を明示的に作成せずに直接文字を並べることも可能です。

C#
// 配列変数を介さず、直接引数に渡す書き方
string[] result = source.Split(',', ';', '/');

この書き方はコードが簡潔になるため、区切り文字が固定されている場合に非常に有効です。

ただし、可読性を考慮して、あまりに多くの文字を指定する場合は配列として定義したほうが管理しやすくなります。

複数の「文字列(string)」を区切り文字にする方法

文字(char)ではなく、「–」や「=>」といった複数の文字からなる文字列を区切り文字として使いたい場合があります。

この場合、string[]を受け取るオーバーロードを使用します。

string配列を利用した分割のコード例

文字列配列を使用する場合、StringSplitOptionsという列挙型を引数に含める必要があります。

これは、区切り文字が連続した場合などの挙動を制御するためのものです。

C#
using System;

class Program
{
    static void Main()
    {
        // 分割対象の文字列(複数の文字列が混在)
        string data = "Apple--Orange=>Banana , Grape";

        // 区切りとなる文字列を配列で定義
        string[] delimiters = { "--", "=>", " , " };

        // Splitメソッドを実行(StringSplitOptionsの指定が必須)
        string[] fruits = data.Split(delimiters, StringSplitOptions.None);

        Console.WriteLine("--- 文字列での分割結果 ---");
        foreach (string fruit in fruits)
        {
            Console.WriteLine($"[{fruit}]");
        }
    }
}
実行結果
--- 文字列での分割結果 ---
[Apple]
[Orange]
[Banana]
[Grape]

なぜStringSplitOptionsが必要なのか

string[]を引数に取るSplitメソッドでは、歴史的な経緯やシグネチャの重複を避けるためにStringSplitOptionsの指定が必須となっています。

通常はNoneを指定すれば良いですが、後述する空の要素を除去したい場合などにこのオプションが真価を発揮します。

空の要素を除去する「StringSplitOptions」の活用

複数の区切り文字を指定すると、区切り文字が連続している箇所(例:「,,」)で空の文字列が配列に含まれてしまうことがあります。

これを防ぐために活用するのがStringSplitOptions.RemoveEmptyEntriesです。

RemoveEmptyEntriesの使用例

以下のコードでは、カンマが連続している部分がありますが、オプションを指定することで綺麗な結果を得ています。

C#
using System;

class Program
{
    static void Main()
    {
        string input = "Red,,Blue,,,Green, Yellow";

        // 区切り文字としてカンマを指定し、空の要素を削除する
        // さらに、.NET 5以降であれば TrimEntries も併用可能
        string[] colors = input.Split(
            new char[] { ',' }, 
            StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries
        );

        Console.WriteLine("--- 空要素除去とトリムの結果 ---");
        foreach (string color in colors)
        {
            Console.WriteLine($"'{color}'");
        }
    }
}
実行結果
--- 空要素除去とトリムの結果 ---
'Red'
'Blue'
'Green'
'Yellow'
オプション名内容
Noneデフォルトの動作。空の要素もそのまま保持します。
RemoveEmptyEntries分割結果から長さ0の文字列(空文字)を除外します。
TrimEntries各要素の前後にある空白文字を削除します(.NET 5以降)。

TrimEntriesは比較的新しい機能ですが、非常に強力です。

分割した後にTrim()をループで回す手間が省けるため、積極的に活用しましょう。

正規表現(Regex.Split)による高度な分割

「数字が含まれていたら分割する」「特定のパターンに一致する場合のみ分割する」といった、文字や固定文字列だけでは対応できない複雑な条件には、正規表現(Regex)を使用します。

Regex.Splitのコード例

System.Text.RegularExpressions名前空間にあるRegex.Splitを使用します。

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

class Program
{
    static void Main()
    {
        // アルファベットと数字が混在した文字列
        string complexData = "User123Group456ID789";

        // 「1つ以上の数字」を区切りとして分割する正規表現パターン
        string pattern = @"\d+";

        // Regex.Splitを使用して分割
        string[] parts = Regex.Split(complexData, pattern);

        Console.WriteLine("--- 正規表現での分割結果 ---");
        foreach (string part in parts)
        {
            if (!string.IsNullOrEmpty(part))
            {
                Console.WriteLine(part);
            }
        }
    }
}
実行結果
--- 正規表現での分割結果 ---
User
Group
ID

正規表現を使うべき場面

正規表現は強力ですが、通常のstring.Splitに比べると処理パフォーマンスが低下する傾向にあります。

以下の基準で使い分けるのがベストです。

string.Splitで十分な場合

固定の文字や文字列が決まっているとき。

Regex.Splitが必要な場合

「数字」「空白文字の連続」「特定の文字種」など、パターンでしか表現できない条件のとき。

大規模データでのパフォーマンスを考慮した分割

C#のSplitメソッドは非常に便利ですが、分割のたびに新しい文字列の配列と文字列インスタンスを生成するという特性があります。

数百万行に及ぶ巨大なログファイルを処理する場合、このメモリ割り当てがボトルネックになる可能性があります。

Span<T> を活用した効率的な分割

最新のC#(.NET Core 2.1以降)では、Span<char>ReadOnlySpan<char>を利用することで、メモリのコピーを抑えた高速な文字列処理が可能です。

直接Splitで配列を作るのではなく、文字列の「範囲」を参照することで、ガベージコレクション(GC)の負荷を大幅に軽減できます。

C#
using System;

class Program
{
    static void Main()
    {
        string largeData = "Data1,Data2,Data3";
        ReadOnlySpan<char> span = largeData.AsSpan();

        Console.WriteLine("--- Spanを用いたメモリ効率の良い処理 ---");
        
        int index;
        while ((index = span.IndexOf(',')) != -1)
        {
            // 新しい文字列を作らず、範囲だけを切り出す(スライス)
            ReadOnlySpan<char> part = span.Slice(0, index);
            Console.WriteLine(part.ToString()); // 表示の際にのみ文字列化
            
            // 残りの部分にスパンを進める
            span = span.Slice(index + 1);
        }
        // 最後の要素を表示
        Console.WriteLine(span.ToString());
    }
}

このように、ReadOnlySpan<char>を利用した「スライス」処理を行うことで、メモリ消費を最小限に抑えつつ、複数の区切り文字を探して処理していくことが可能です。

まとめ

C#における文字列分割は、単純なものから高度なものまで多様な手法が用意されています。

  • 基本: char[]params char[]を使用して、複数の文字で分割する。
  • 文字列: string[]StringSplitOptionsを組み合わせて、特定のキーワードで分割する。
  • クレンジング: RemoveEmptyEntriesTrimEntriesを活用して、不要な空文字や空白を排除する。
  • 柔軟性: 複雑なパターンにはRegex.Splitを利用する。
  • 最適化: 大規模データや高頻度の処理ではSpan<char>による最適化を検討する。

それぞれの特徴を理解し、状況に合わせて最適な方法を選択することで、より効率的で読みやすいC#プログラムを記述できるようになります。

まずは最も汎用的なchar配列による分割からマスターし、必要に応じて高度なテクニックを取り入れていきましょう。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!