🙄

.NETの正規表現 - キャプチャ

2024/04/24に公開

.NETの正規表現

.NETでは正規表現が標準で提供されます。
https://learn.microsoft.com/ja-jp/dotnet/standard/base-types/regular-expression-language-quick-reference
あらゆる環境で利用されることを想定しているようで、数ある正規表現エンジンの中でもかなり強力な部類だと思います。
マッチした結果はMatchクラスからアクセスできます。

キャプチャ

()でキャプチャできるのは他のエンジンと同じです。(の出現順に1から番号が振られます。Groupsプロパティでアクセスできます。
(?:(\d+) )+のように複数回マッチしたら…最後の値が得られる、だけじゃないんです。Groupクラスは最後の値を指すValueプロパティだけでなく、Capturesプロパティがあり、一連のマッチにアクセスできます。

(?<name>subexpression)(?'name'subexpression)で名前付きキャプチャもできます。これも他の言語にもあります。()と異なり連番ではなく名前でアクセスできます。
名前でアクセスできるとなると、すぐに思い付くのは「同じ名前を付けたらどうなるの?」ですが、その点もちゃんと考慮されています。

1 つの正規表現で同じグループ名を繰り返すことができます。(略)
次の例では、正規表現 \D+(?<digit>\d+)\D+(?<digit>\d+)?digitという名前のグループの 2 回の出現が含まれています。

これが他の言語、例えばPythonだと(?P<name>...)はこう説明されています。

グループ名は有効な Python 識別子でなければならず、各グループ名は 1 個の正規表現内で一度だけ定義されていなければなりません。

動的プロパティ

ここで突然のF#です。F#にはDynamic Lookup Operatorというものがあります。右辺値に書いた識別子が文字列として渡されます。これは名前付きプロパティとうまくマッチします。

let inline (?) (m : Match) (name : string) = m.Groups[name]

こう定義すると

let m = Regex.Match(text, @"(?m)^(?<id>\d+)#(?<name>[^#]+)#", )
let id = Int32.Parse(m?id.ValueSpan)
let name = m?name.Value

と表現できます。

Discussion