.NET アプリの C# のコードで、正規表現のパターンにコメントをつける方法を書きます。
上の画像を見れば一目瞭然で、それ以上の説明は不要かもしれませんが、それでは記事としてはちょっと寂しいので追加情報なども以下に書いておきます。
正規表現については、自分的には Microsoft のドキュメント「ASP.NET の正規表現」
が一番分かりやすく、いつも参考にさせてもらっています。
おかげさまで、自分でもある程度パターンを作れるようにはなったのですが、自分で作っておきながら後になって読むと意味不明ということがあります。
そういう時のために、正規表現パターンにコメントをつけておくと良いという Microsoft の記事を見つけて真似しています。
その記事は見つからなくなってしまったので、以前自分が書いたコードを探して、それを参考にしてコメントをつけていましたが、探して見つけるのが結構大変ということで、書いておくことにしました。
以下は表題の「正規表現パターンにコメント」とは関係ない話ですが、上の画像のコードに関してついでに書いておきます。
上の画像の例は、パスワードの文字列で、条件として「半角大文字アルファベットと半角数字のみの 4 文字以上、8 文字以下で構成され、それぞれ最低 1 文字を含む」という正規表現のパターンです。
そのような条件の場合、上に紹介した「ASP.NET の正規表現」のページの「高度なトピック」のセクションに書いてある "ルックアラウンド処理" を利用するのが便利だと思います。
「正の先読み」および「負の先読み」の両方のケースで書いてみました。前者が下のコードの regex1、後者が regex2 です。
using System.Text.RegularExpressions;
namespace ConsoleAppRegex
{
internal class Program
{
static void Main(string[] args)
{
Regex regex1 = new Regex(@"
^ # 開始のアンカー
(?=.*\d) # 数字が最低 1 文字あること
(?=.*[A-Z]) # 英大文字が最低 1 文字あること
[A-Z0-9]{4,8} # 英大文字または数字が 4 ~ 8 文字
$ # 終了のアンカー",
RegexOptions.IgnorePatternWhitespace);
Regex regex2 = new Regex(@"
(?!^[0-9]*$) # 全部が数字ということはない
(?!^[A-Z]*$) # 全部が英大文字ということはない
^ # 開始のアンカー
([A-Z0-9]{4,8}) # 英大文字または数字が 4 ~ 8 文字
$ # 終了のアンカー",
RegexOptions.IgnorePatternWhitespace);
string[] testStrings = { "AB1", "AB12", "ABCDEF", "123456",
"ABCDEFG1", "1234567A", "ABCD12345",
"ABC123dE", "ABCあ123", "ABC%1234" };
foreach (string s in testStrings)
{
Console.WriteLine($"{s} => {regex1.IsMatch(s)} (1)");
Console.WriteLine($"{s} => {regex2.IsMatch(s)} (2)");
}
/*
結果は:
AB1 => False (1)
AB1 => False (2)
AB12 => True (1)
AB12 => True (2)
ABCDEF => False (1)
ABCDEF => False (2)
123456 => False (1)
123456 => False (2)
ABCDEFG1 => True (1)
ABCDEFG1 => True (2)
1234567A => True (1)
1234567A => True (2)
ABCD12345 => False (1)
ABCD12345 => False (2)
ABC123dE => False (1)
ABC123dE => False (2)
ABCあ123 => False (1)
ABCあ123 => False (2)
ABC%1234 => False (1)
ABC%1234 => False (2)
*/
}
}
}
「正の先読み」というのが (?=<pattern>)
という形のもので、対象文字列を先読みしていって の条件に合えば true になります。例えば、上のコードでいうと regex1 の (?=.*\d)
が該当します。<pattern>
は .*\d
で、「任意の文字 0 回以上の繰り返しのあと数字がある」という条件になります。
「負の先読み」というのは (?!<pattern>)
という形のもので、「正の先読み」の逆すなわち否定になり、<pattern>
の条件に合わないものが true
になります。上のコードの regex2 の (?!^[0-9]*$)
の場合、<pattern>
は ^[0-9]*$
で、「文字列の最初から最後まで全ての文字が数字ではない」という条件になります。