[C#] Advanced Replacement with Regex (Substitution Patterns and MatchEvaluator)

While the String.Replace method can only perform simple string substitutions, Regex.Replace enables advanced processing, such as “rewriting parts that match a pattern” or “replacing text with the result of a programmatic calculation.”

In this article, I will explain two techniques: format conversion using Substitution Patterns ($1, $2…) and dynamic value conversion using Lambda Expressions (MatchEvaluator).

目次

Table of Contents

  1. Capture Groups and Substitution Patterns ($1, $2…)
  2. Dynamic Replacement with MatchEvaluator (Lambda Expressions)
  3. Implementation Sample
  4. Execution Result
  5. Explanation and Technical Points

1. Capture Groups and Substitution Patterns ($1, $2…)

Parts of a regular expression grouped with parentheses () can be referenced (reused) in the replacement string using symbols like $1 and $2. This makes it easy to reorder or format data.

2. Dynamic Replacement with MatchEvaluator (Lambda Expressions)

If you want to perform logic such as “calculating matched numbers” or “converting case” instead of using a fixed replacement string, you can specify a delegate (Lambda expression) as the third argument.

Implementation Sample

The following code implements two different scenarios:

  1. Personal Information Masking: Masking specific digits of a phone number (Using Substitution Patterns).
  2. Price Calculation: Finding numbers in text and rewriting them with tax included (Using Lambda Expressions).
using System;
using System.Text.RegularExpressions;

public class Program
{
    public static void Main()
    {
        // -------------------------------------------------------
        // Pattern 1: Format change using Substitution Patterns ($1, $2)
        // -------------------------------------------------------
        Console.WriteLine("--- 1. Phone Number Masking ---");
        
        string personalData = "Contact A: 090-1234-5678, Contact B: 080-9876-5432";
        
        // Regex: Search for (3 digits)-(4 digits)-(4 digits)
        // By enclosing each part in groups (), we can reference them as $1, $2, $3
        string phonePattern = @"(\d{3})-(\d{4})-(\d{4})";

        // Replacement specification:
        // $1   -> First 3 digits (090)
        // **** -> Fixed masking text
        // $3   -> Last 4 digits (5678)
        string maskedData = Regex.Replace(personalData, phonePattern, "$1-****-$3");

        Console.WriteLine($"Original: {personalData}");
        Console.WriteLine($"Result  : {maskedData}");


        // -------------------------------------------------------
        // Pattern 2: Dynamic calculation using Lambda (MatchEvaluator)
        // -------------------------------------------------------
        Console.WriteLine("\n--- 2. Price Tax Calculation ---");

        string priceList = "Apple: 100yen, Orange: 250yen, Banana: 80yen";

        // Regex: Search for consecutive digits (\d+)
        string numberPattern = @"\d+";

        // Regex.Replace(input, pattern, MatchEvaluator delegate)
        // This lambda is called for every match found
        string taxedList = Regex.Replace(priceList, numberPattern, (Match m) =>
        {
            // 1. Convert the matched string (number) to an integer
            int price = int.Parse(m.Value);

            // 2. Calculate tax (add 10%)
            int taxIncluded = (int)(price * 1.1);

            // 3. Return as string (this becomes the replacement text)
            return taxIncluded.ToString();
        });

        Console.WriteLine($"Original: {priceList}");
        Console.WriteLine($"Taxed   : {taxedList}");
    }
}

Execution Result

--- 1. Phone Number Masking ---
Original: Contact A: 090-1234-5678, Contact B: 080-9876-5432
Result  : Contact A: 090-****-5678, Contact B: 080-****-5432

--- 2. Price Tax Calculation ---
Original: Apple: 100yen, Orange: 250yen, Banana: 80yen
Taxed   : Apple: 110yen, Orange: 275yen, Banana: 88yen

Explanation and Technical Points

1. Substitution Patterns ($1, $2…)

Mechanism: Parentheses () in a regular expression are numbered sequentially from left to right (if nested, the outer one takes precedence). Usage: Effective for date format conversion (e.g., 2025/12/31 -> 31-12-2025) or rewriting HTML tags.

2. MatchEvaluator (Dynamic Replacement)

Mechanism: The specified method (Lambda expression) is called every time the pattern matches. The argument Match contains the matched information, and the string returned by the method replaces that part. Usage:

  • Numerical calculations (as seen in the example).
  • Dictionary lookups (e.g., converting an ID to a Name).
  • Complex conditional branching (e.g., replacing only if a specific value is met).

By mastering these two techniques, you can concisely write “text processing programs” that go beyond simple character replacement.

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次