C# Tips | 文字列操作:指定文字列を置換する

Web APP C#
スポンサーリンク
スポンサーリンク

C#で指定文字列を置換する方法

C#で文字列を扱っていると、特定の文字や単語を別の文字列に置き換えたい場面がよくあります。たとえば、文章に含まれる古い商品名を新しい商品名に変更したり、ファイルパスの区切り文字を統一したり、入力された文字列から不要な記号を取り除いたりする処理です。

このような処理には、C#の Replace メソッドを使用します。基本的な使い方を覚えておけば、文字列の整形、データの加工、ログの編集、入力内容の前処理など、さまざまな業務で活用できます。

この記事では、プログラミング初心者の方にも理解できるように、指定文字列を置換する基本から、実務で再利用できるメソッド、注意点、安全に扱うための考え方まで順番に解説します。

指定文字列を置換するとは

文字列の置換とは、元の文字列に含まれる特定の文字や文字列を、別の文字列に変更する処理です。

たとえば、次の文章があるとします。

C#は難しい。C#を使って業務を効率化したい。

この文章に含まれる「C#」を「C#プログラミング」に置き換えると、次のようになります。

C#プログラミングは難しい。C#プログラミングを使って業務を効率化したい。

このように、指定した文字列を別の文字列に置き換えることで、文章をまとめて編集できます。

C#では、文字列の置換に string.Replace メソッドを使用します。基本的な書き方は次のとおりです。

// 置換対象の文字列を用意します。
string text = "C#は便利です。";

// 「便利」を「実用的」に置き換えます。
string result = text.Replace("便利", "実用的");

// 置換後の文字列を表示します。
Console.WriteLine(result);
C#

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

C#は実用的です。

Replace の最初の引数には置き換えたい文字列を指定し、2番目の引数には置き換え後の文字列を指定します。

text.Replace("置換したい文字列", "置換後の文字列");
C#

この形式を覚えておけば、基本的な文字列置換を実装できます。

Replaceメソッドの基本的な使い方

特定の単語を別の単語に置き換える

最も基本的な使い方は、文章に含まれる特定の単語を別の単語に置き換えることです。

string text = "旧商品は販売終了です。旧商品のお問い合わせはこちらです。";

// 文章内の「旧商品」を「新商品」に置き換えます。
string result = text.Replace("旧商品", "新商品");

Console.WriteLine(result);
C#

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

新商品は販売終了です。新商品のお問い合わせはこちらです。

この例では、置換対象の「旧商品」が2か所に存在します。Replace は該当するすべての箇所を置き換えます。

最初に見つかった1か所だけを置き換えるのではなく、対象となる文字列をすべて置き換えることが重要なポイントです。

特定の文字を置き換える

単語だけでなく、1文字を置き換えることもできます。

たとえば、ハイフンをアンダースコアに置き換える場合は、次のように記述します。

string text = "customer-order-number";

// ハイフンをアンダースコアに置き換えます。
string result = text.Replace("-", "_");

Console.WriteLine(result);
C#

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

customer_order_number

このような処理は、ファイル名や識別子、データの形式を統一するときに役立ちます。

ただし、置換後の文字列が、使用するシステムやファイル形式のルールに適合しているかどうかは別途確認する必要があります。

文字列を削除する

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

string text = "商品コード:ABC-123";

// 「商品コード:」を空文字に置き換えて削除します。
string result = text.Replace("商品コード:", "");

Console.WriteLine(result);
C#

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

ABC-123

このように、空文字に置き換えることで、特定の文字列を取り除くことができます。

ただし、文字列を削除すると、元の文章の意味やデータの構造が変わる場合があります。特に、入力データやファイル形式を処理する場合は、削除対象が本当に不要な文字列なのかを確認してください。

Replaceの戻り値と文字列の不変性

C#の文字列操作で初心者が間違えやすいのが、Replace を実行しても元の文字列自体は変更されないという点です。

C#の string は不変、つまり一度作成した文字列の内容を直接変更できない型です。Replace は元の文字列を書き換えるのではなく、置換後の新しい文字列を返します。

次のコードを見てみましょう。

string text = "りんごを食べます。";

// 置換後の文字列を受け取らずに実行します。
text.Replace("りんご", "みかん");

// 元の文字列を表示します。
Console.WriteLine(text);
C#

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

りんごを食べます。

置換処理を実行していますが、結果を変数に保存していないため、text の内容は変わりません。

正しく置換後の文字列を使用するには、次のように記述します。

string text = "りんごを食べます。";

// Replaceの戻り値を変数に保存します。
text = text.Replace("りんご", "みかん");

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

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

みかんを食べます。

別の変数に結果を保存する書き方もできます。

string originalText = "りんごを食べます。";

// 元の文字列を残したまま、置換後の文字列を取得します。
string replacedText = originalText.Replace("りんご", "みかん");

Console.WriteLine(originalText);  // 元の文字列
Console.WriteLine(replacedText); // 置換後の文字列
C#

この方法なら、置換前と置換後の内容を両方保持できます。

元データを変更せずに加工結果だけを別に保存したい場合は、別の変数を使用すると分かりやすくなります。

複数の文字列を順番に置換する

ひとつの文字列に対して、複数の置換処理を実行することもできます。

たとえば、文章に含まれる複数の表現をまとめて変更する場合です。

string text = "旧商品は旧価格で販売しています。";

// 商品名を置き換えます。
text = text.Replace("旧商品", "新商品");

// 価格の表現を置き換えます。
text = text.Replace("旧価格", "新価格");

// 結果を表示します。
Console.WriteLine(text);
C#

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

新商品は新価格で販売しています。

このように、Replace を順番に実行することで、複数の置換を行えます。

ただし、置換処理の順番によっては結果が変わる場合があります。

置換する順番に注意する

次の例を見てみましょう。

string text = "ABC";

// 先に「AB」を「X」に置き換えます。
text = text.Replace("AB", "X");

// 続けて「X」を「Y」に置き換えます。
text = text.Replace("X", "Y");

Console.WriteLine(text);
C#

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

YC

最初の置換で「ABC」が「XC」になり、次の置換で「YC」になります。

一方、処理する順番を変えたり、置換後の文字列が別の置換対象に一致するように設定したりすると、意図しない結果になることがあります。

たとえば、「A」を「B」に置き換えたあとで「B」を「C」に置き換えると、最初から存在していた「B」だけでなく、置換によって生成された「B」も「C」になります。

複数の置換を行う場合は、置換後の文字列が次の置換対象に一致しないかどうかを確認しておきましょう。

大文字と小文字を区別して置換する

英語などの文字列を置換する場合は、大文字と小文字の扱いにも注意が必要です。

たとえば、次の文字列を考えてみましょう。

Apple apple APPLE

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

string text = "Apple apple APPLE";

// 小文字の「apple」を置き換えます。
string result = text.Replace("apple", "orange");

Console.WriteLine(result);
C#

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

Apple orange APPLE

小文字の「apple」だけが置き換えられ、先頭が大文字の「Apple」やすべて大文字の「APPLE」はそのまま残ります。

大文字と小文字を区別せずに置換したい場合は、StringComparison を指定できるオーバーロードを使用します。

using System;

// 置換対象の文字列を用意します。
string text = "Apple apple APPLE";

// 大文字と小文字を区別せずに置換します。
// OrdinalIgnoreCaseは、カルチャに依存しない比較方法です。
string result = text.Replace(
    "apple",
    "orange",
    StringComparison.OrdinalIgnoreCase);

Console.WriteLine(result);
C#

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

orange orange orange

このオーバーロードは、.NET Core 2.1以降や対応する.NETのバージョンで利用できます。古い.NET Frameworkなどを対象にする場合は、使用できるAPIを確認してください。

OrdinalIgnoreCaseを使用する理由

StringComparison.OrdinalIgnoreCase は、大文字と小文字を区別せずに文字列を比較するための指定です。ユーザー名の形式や、カルチャに左右されない識別子などを扱う場合に適しています。

ただし、すべての言語の文章を同じルールで置換すればよいわけではありません。自然言語の文章では、言語や地域によって大文字・小文字の規則が異なる場合があります。

業務用の識別子やコードなどを扱う場合は OrdinalIgnoreCase が適していることが多い一方、自然言語の文章を処理する場合は、目的に合った比較方法を選択する必要があります。

nullや空文字を安全に扱う

実務では、置換対象の文字列が必ず存在するとは限りません。

たとえば、データベースから取得した値や、ユーザーが入力した値を処理する場合、文字列が null や空文字になっている可能性があります。

null に対してインスタンスメソッドの Replace を呼び出すと、NullReferenceException が発生します。

そのため、置換処理の前に対象の文字列を確認することが大切です。

string? text = null;

// nullの場合はReplaceを呼び出さず、空文字として扱います。
string result = string.IsNullOrEmpty(text)
    ? string.Empty
    : text.Replace("古い文字", "新しい文字");

Console.WriteLine(result);
C#

このコードでは、text が null または空文字の場合は空文字を返し、それ以外の場合にだけ置換処理を実行しています。

ただし、null と空文字は意味が異なる場合があります。null は値が存在しないことを示し、空文字は値が存在しているものの内容が空であることを示す場合があります。

データベースや業務システムでこの違いが重要な場合は、どちらも空文字に統一するのではなく、元の意味を保持するように設計してください。

nullならnullを返す方法

元の文字列が null だった場合、その状態を維持したいこともあります。

その場合は、次のように記述できます。

string? text = null;

// nullならnullを維持し、それ以外の場合に置換します。
string? result = text?.Replace("古い文字", "新しい文字");

Console.WriteLine(result ?? "(値なし)");
C#

?. は、左側の値が null でない場合にだけメソッドを呼び出すための null 条件演算子です。

この例では、text が null なので result も null になります。表示するときだけ ?? を使って「(値なし)」という文字列に置き換えています。

このように、null をどのように扱うかは、処理の目的に応じて決めましょう。

置換対象が存在しない場合

指定した文字列が元の文字列に含まれていない場合、Replace は例外を発生させず、元の文字列と同じ内容の文字列を返します。

string text = "今日は晴れです。";

// 対象の「雨」が存在しないため、文字列は変わりません。
string result = text.Replace("雨", "雪");

Console.WriteLine(result);
C#

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

今日は晴れです。

対象が存在しないことを特別なエラーとして扱う必要はありません。ただし、置換が実際に行われたかどうかを知りたい場合は、置換前後の文字列を比較するなど、別の方法で判定する必要があります。

なお、文字列の内容を比較するときは、何をもって同じと判断するのかを明確にしておきましょう。大文字と小文字を区別するかどうかなど、比較条件によって結果が変わる場合があります。

実務で使える置換メソッドを作成する

同じ置換処理を複数の場所で使う場合は、専用のメソッドにまとめると便利です。

ここでは、次の仕様で実装します。

  • 元の文字列が null の場合は、null を返します。
  • 置換対象が null または空文字の場合は、引数の指定ミスとして例外を発生させます。
  • 置換後の文字列が null の場合は、空文字として扱います。
  • それ以外の場合は、指定した文字列をすべて置換します。
  • 大文字と小文字を区別するかどうかを指定できます。

次のコードは、.NET Core 2.1以降など、StringComparison を指定する Replace が利用できる環境を想定しています。

/// <summary>
/// 指定した文字列を別の文字列に置き換えます。
/// </summary>
/// <param name="text">置換対象の元の文字列</param>
/// <param name="oldValue">置き換えたい文字列</param>
/// <param name="newValue">置き換え後の文字列</param>
/// <param name="comparisonType">大文字と小文字などの比較方法</param>
/// <returns>置換後の文字列。元の文字列がnullならnull</returns>
static string? ReplaceText(
    string? text,
    string oldValue,
    string? newValue,
    StringComparison comparisonType = StringComparison.Ordinal)
{
    // 元の文字列がnullなら、nullを維持します。
    if (text is null)
    {
        return null;
    }

    // 置換対象がnullなら、引数の指定ミスとして例外を発生させます。
    if (oldValue is null)
    {
        throw new ArgumentNullException(nameof(oldValue));
    }

    // 空文字を置換対象にすると、意図しない結果になり得るため禁止します。
    if (oldValue.Length == 0)
    {
        throw new ArgumentException(
            "置換対象には空文字以外を指定してください。",
            nameof(oldValue));
    }

    // 置換後の文字列がnullなら、空文字として扱います。
    newValue ??= string.Empty;

    // 指定した比較方法で、対象となる文字列を置換します。
    return text.Replace(oldValue, newValue, comparisonType);
}
C#

このメソッドは、次のように使用できます。

string text = "Apple apple APPLE";

// 大文字と小文字を区別せずに置換します。
string? result = ReplaceText(
    text,
    "apple",
    "orange",
    StringComparison.OrdinalIgnoreCase);

// 置換結果を表示します。
Console.WriteLine(result);
C#

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

orange orange orange

置換対象の空文字を禁止する理由

置換対象に空文字を指定すると、通常の「特定の文字列を探して置き換える」という意図が不明確になります。

そのため、このメソッドでは oldValue が空文字の場合に例外を発生させています。こうすることで、呼び出し側が引数を間違えた場合に、問題を早い段階で発見できます。

一方、置換後の文字列 newValue は空文字を許可しています。空文字に置き換えることは、対象の文字列を削除するという明確な用途があるためです。

なお、oldValue の型を string と宣言していても、呼び出し側から null が渡される可能性はあります。実行時の入力を信頼しすぎず、必要な検証を行うことが大切です。

特定の文字列だけを削除する実務例

指定文字列の置換は、不要な文字列を削除する処理にも使えます。

たとえば、商品コードに含まれるハイフンを削除したい場合は、次のように記述します。

string productCode = "AB-123-CD";

// ハイフンを空文字に置き換えて削除します。
string normalizedCode = productCode.Replace("-", "");

Console.WriteLine(normalizedCode);
C#

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

AB123CD

このような処理は、入力形式を統一するときに便利です。

ただし、すべてのハイフンを削除してよいかどうかは、データの仕様によって異なります。商品コードのハイフンが意味を持つ場合は、削除すると別のコードと区別できなくなる可能性があります。

入力値の見た目を整える処理と、データそのものの意味を変更する処理は、分けて考えるようにしましょう。

注意点:Replaceは正規表現ではない

Replace は、指定した文字列そのものを検索して置き換えるメソッドです。正規表現のパターンを指定するメソッドではありません。

たとえば、次のコードを見てみましょう。

string text = "A1 B2 C3";

// 数字を「X」に置き換えたいつもりのコードです。
string result = text.Replace("[0-9]", "X");

Console.WriteLine(result);
C#

このコードでは、[0-9] という文字列そのものを探します。数字を表す正規表現パターンとして解釈されるわけではありません。

そのため、実行結果は次のとおりです。

A1 B2 C3

数字をすべて「X」に置き換えたい場合は、Regex.Replace を使用します。

using System.Text.RegularExpressions;

string text = "A1 B2 C3";

// 正規表現で数字を表すパターンを指定し、数字をXに置き換えます。
string result = Regex.Replace(text, "[0-9]", "X");

Console.WriteLine(result);
C#

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

AX BX CX

Regex.Replace は、数字や特定の形式に一致する部分など、複雑な条件で置換したい場合に便利です。

ただし、正規表現は通常の文字列置換よりも複雑になりやすく、パターンの書き方によっては処理負荷が高くなる場合があります。単純な文字列を置き換えるだけなら Replace を使用し、パターンによる検索が必要な場合に正規表現を選ぶとよいでしょう。

注意点:ファイルパスやURLを安易に置換しない

Replace は便利ですが、ファイルパスやURLなど、一定の構造やルールを持つ文字列を扱う場合には注意が必要です。

たとえば、次のコードはバックスラッシュをスラッシュに置き換えます。

string path = @"C:\Work\Reports\result.txt";

// バックスラッシュをスラッシュに置き換えます。
string result = path.Replace("\\", "/");

Console.WriteLine(result);
C#

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

C:/Work/Reports/result.txt

表示用に区切り文字を統一したい場合などには役立ちます。しかし、ファイルシステムに渡すパスを作成する場合は、単純な置換よりも Path.Combine などの専用APIを使用するほうが適切なことがあります。

また、URLの文字列を安易に置換すると、パスやクエリ文字列の意味が変わる可能性があります。URLを加工する場合は、URIを解析するためのAPIを使い、変更したい部分を明確にして処理することをおすすめします。

構造を持つデータは、単なる文字列として一括置換するのではなく、その形式に対応したAPIを優先することが、安全で保守しやすい実装につながります。

セキュリティ面で注意すること

ユーザー入力や外部システムから受け取った文字列を置換する場合は、置換後の値がどのように使用されるかを考慮する必要があります。

たとえば、入力された文字列から特定の記号を削除するだけでは、SQLインジェクションやクロスサイトスクリプティング(XSS)などの対策として十分ではありません。

SQL文を作成する場合は、文字列の置換で入力値を加工するのではなく、パラメーター化されたクエリを使用します。HTMLに表示する場合は、出力先に応じた適切なエンコードを使用します。

// 注意:入力値を単純に置換してSQL文へ連結する方法は避けてください。
// string sql = "SELECT * FROM Users WHERE Name = '" +
//              userInput.Replace("'", "") + "'";

// データベースアクセスでは、使用するライブラリの
// パラメーター化されたクエリ機能を利用してください。
C#

文字列の置換は、データを整形するための機能です。入力値が安全であることを保証する機能ではありません。

また、パスワードやアクセストークンなどの機密情報が含まれる文字列は、特定の部分を置換するだけでは安全に扱えるとは限りません。ログへの出力や外部への送信を行う前に、情報の取り扱いルールに沿って適切に除外・マスキングする必要があります。

すぐに使える基本テンプレート

最後に、指定文字列を置換する最も基本的なテンプレートを紹介します。

/// <summary>
/// 指定した文字列を別の文字列に置き換えます。
/// </summary>
/// <param name="text">元の文字列</param>
/// <param name="oldValue">置換対象の文字列</param>
/// <param name="newValue">置換後の文字列</param>
/// <returns>置換後の文字列</returns>
static string ReplaceTextBasic(
    string text,
    string oldValue,
    string newValue)
{
    // 元の文字列がnullの場合は例外を発生させます。
    ArgumentNullException.ThrowIfNull(text);

    // 置換対象がnullの場合は例外を発生させます。
    ArgumentNullException.ThrowIfNull(oldValue);

    // 置換後の文字列がnullの場合は例外を発生させます。
    ArgumentNullException.ThrowIfNull(newValue);

    // 空文字を置換対象に指定することは禁止します。
    if (oldValue.Length == 0)
    {
        throw new ArgumentException(
            "置換対象には空文字以外を指定してください。",
            nameof(oldValue));
    }

    // 指定した文字列をすべて置き換えて返します。
    return text.Replace(oldValue, newValue);
}
C#

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

string text = "この商品は旧モデルです。";

// 「旧モデル」を「新モデル」に置き換えます。
string result = ReplaceTextBasic(
    text,
    "旧モデル",
    "新モデル");

// 結果を表示します。
Console.WriteLine(result);
C#

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

この商品は新モデルです。

このテンプレートでは、引数が null でないことと、置換対象が空文字でないことを確認しています。ArgumentNullException.ThrowIfNull は、.NET 6以降で使用できます。古い.NET環境を対象とする場合は、if (text is null) などを使用した明示的なチェックに置き換えてください。

なお、このテンプレートは null を許可しない設計です。null を受け取ったときに空文字を返すのか、null のまま維持するのか、例外を発生させるのかは、アプリケーションの仕様に合わせて選択してください。

まとめ

C#で指定文字列を置換するには、string.Replace メソッドを使用します。置換対象の文字列と置換後の文字列を指定するだけで、元の文字列に含まれる該当箇所をまとめて置き換えられます。

実務で使用する場合は、次のポイントを押さえておきましょう。

  • Replace は、指定した文字列に一致するすべての箇所を置き換えます。
  • 置換後の文字列は新しく返されるため、戻り値を変数に保存する必要があります。
  • 通常の Replace では、大文字と小文字を区別します。
  • null や空文字の扱いを、アプリケーションの仕様に合わせて決めます。
  • 複数の置換処理では、処理の順番によって結果が変わることがあります。
  • 正規表現による置換が必要な場合は、Regex.Replace を使用します。
  • ファイルパスやURLなど、構造を持つデータは専用APIを優先します。
  • 文字列の置換だけでは、セキュリティ上の問題を防げない場合があります。

文字列置換はシンプルな処理ですが、入力値の検証や戻り値の扱い、置換順序などを正しく理解しておくことで、より安全で保守しやすいプログラムを作成できます。まずは基本的な Replace から使い始め、必要に応じて比較方法や正規表現、専用メソッドへと応用していきましょう。

タイトルとURLをコピーしました