Rubyの正規表現をC#で書いてみた

# 動機

かなり前にRubyを使ってたことがあり、Rubyで簡潔に書ける正規表現をC#で書いたらどうなるのかを書いてみたいと思った。
(C#好きですが、この記事でRuby→C#への乗り換えを推奨しているつもりはないですので、あしからず。)

# やってみたこと

[Ruby 正規表現のまとめ](https://qiita.com/agotoh/items/87960d256e427d5673a9)
で書かれている内容がいい感じなので、ほぼ同じ内容で、C#でやったらどうなるかを勝手に書いてみました。
コードはRubyより長くはなるけど、対応する方法はあると言えそう。

```csharp

using System;
using System.Text.RegularExpressions;

class Samples
{
    // $& 相当
    static void Sample1()
    {
        Console.WriteLine("--- Sample1 ---");
        Regex r = new Regex("C.");

        Match m = r.Match("ABCDE");
        if (m.Success) { // マッチしたらtrue
            Console.WriteLine(m.Groups[0].Value); // $& "CD"
        }
    }

    // $1, $2, $3, ... 相当
    static void Sample2()
    {
        Console.WriteLine("--- Sample2 ---");
        Regex r = new Regex("(.)(.)(.)");

        Match m = r.Match("ABC");
        if (m.Success) {
            Console.WriteLine(m.Groups[1].Value); // $1 "A"
            Console.WriteLine(m.Groups[2].Value); // $2 "B"
            Console.WriteLine(m.Groups[3].Value); // $3 "C"
        }
    }

    // scan 相当
    static void Sample3()
    {
        Console.WriteLine("--- Sample3 ---");
        Regex r = new Regex(".a");

        MatchCollection mc = r.Matches("abracatabra");
        foreach (Match m in mc) {
            Console.WriteLine(m.Groups[0].Value);
            // "ra"
            // "ca"
            // "ta"
            // "ra"
        }
    }

    // sub 相当
    static void Sample4()
    {
        Console.WriteLine("--- Sample4 ---");
        string str = "abc_def__g__hi";
        Regex r = new Regex("_+");

        Console.WriteLine(r.Replace(str, " ", 1)); // 3個目のパラメータ(1)が回数
        // "abc def__g__hi"
    }

    // gsub 相当
    static void Sample5()
    {
        Console.WriteLine("--- Sample5 ---");
        string str = "abc_def__g__hi";
        Regex r = new Regex("_+");

        Console.WriteLine(r.Replace(str, " "));
        // gsub "abc def g hi"
    }

    // gsub 相当 その2
    static void Sample6()
    {
        Console.WriteLine("--- Sample6 ---");
        string str = "abracatabra";
        Regex r = new Regex(".a");

        Console.WriteLine(r.Replace(str, "<$0>"));
        // "ab<ra><ca><ta>b<ra>"
    }

    // Regexp.escape 相当
    static void Sample7()
    {
        Console.WriteLine("--- Sample7 ---");
        Console.WriteLine(Regex.Escape("abc*def"));
        // "abc\*def"
    }

    // =~ 相当(index取得)
    static void Sample8()
    {
        Console.WriteLine("--- Sample8 ---");
        Regex r = new Regex("On");
        string str = "RubyOnRails";

        Match m = r.Match(str);

        if (m.Success) {
            int index = m.Groups[0].Captures[0].Index; // =~ 相当 (一致箇所のindexを返す)
            int length = m.Groups[0].Captures[0].Length;
            Console.WriteLine("Index:" + index.ToString());
            Console.WriteLine("Length:" + length.ToString());

            Console.WriteLine(str.Substring(0,index)); // $`
            Console.WriteLine(m.Groups[0].Value); // $&
            Console.WriteLine(str.Substring(index+length)); // $'
        }
    }

    [STAThread]
    static void Main()
    {
        Sample1();
        Sample2();
        Sample3();
        Sample4();
        Sample5();
        Sample6();
        Sample7();
        Sample8();
    }
}
```

ちなみにC#では、(C言語と違い)バックスラッシュ文字をエスケープする文字列記法 `@""` があるので、正規表現を使うときには、こっちを使うほうが間違えにくいです。
(`"hoge\\[foo"`は`@"hoge\[foo"`と書ける。)


# 実行結果

```

--- Sample1 ---
CD
--- Sample2 ---
A
B
C
--- Sample3 ---
ra
ca
ta
ra
--- Sample4 ---
abc def__g__hi
--- Sample5 ---
abc def g hi
--- Sample6 ---
ab<ra><ca><ta>b<ra>
--- Sample7 ---
abc\*def
--- Sample8 ---
Index:4
Length:2
Ruby
On
Rails
```