Pascal 形式や camel 形式を単語に分割する正規表現


Pascal 形式や camel 形式は単語の頭を大文字にして連結する形式です (例: HelloWorld, backgroundColor)。例えば C# ではメソッド名や変数名これらの形式が一般的に用いられます。 Pascal/camel 形式のフレーズを単語に戻せるとうれしいことがあります。

C# で普通にやると次のようになります。

for (int index = s.Length - 1; index > 0; index++)
{
	if (Char.IsUpper(s[index]))
	{
		s = s.Insert(index, " ");
	}
}

これを正規表現でやると次のようになります。

Regex regex = new Regex(@"((?<=\S)\p{Lu})");
s = regex.Replace(s, " $1");

これは次のように解釈できます。

  1. \S は空白文字以外の文字にマッチします。
  2. \p{Lu} は大文字にマッチします。
  3. (?<=) はゼロ幅の肯定的後読みアサーションで,続く表現がこのグループに続くことを意味します。つまり, \p{Lu} でマッチした文字の前には \S でマッチする空白文字以外の文字が存在します。
  4. 全体が () でグループ化されているので, \p{Lu} でマッチした文字が $1 として参照されます。 \S でマッチした文字はゼロ幅グループなので $1 には含まれません。

まとめると,「空白文字以外の文字に続く大文字」にマッチすることになります。この文字は $1 で参照されるので, Replace(" $1") によって,「空白文字以外の文字に続く大文字」の前にスペースが挿入されることになります。

なお, .NET Framework における正規表現についての詳細は MSDN の『.NET Framework の正規表現』を参照してください。

最後におまけとして,数字を含む Pascal/camel 形式のフレーズを単語に分割する方法を紹介します。例えば "Foo123Bar" を "Foo 123 Bar" に分割します。

Regex regex = new Regex(@"((?<=\S)\p{Lu}|(?<=[^\s\d])(?!<\d)\d)");
regex.Replace("Foo123Bar", " $1");  // "Foo 123 Bar"

[note]
[2010-07-23 14:50] 正規表現で括弧の対応が正しくなかったのを修正。
[/note]