regex 为什么这个.net正则表达式在自由空间模式下会失败?

11dmarpk  于 2023-01-10  发布在  .NET
关注(0)|答案(1)|浏览(124)

我正在尝试使用我在freespace模式下创建的正则表达式,这样我就可以添加注解并保持它在将来的可维护性。下面的程序是这个问题的一个示例,但是我遇到这个问题的实际正则表达式要复杂得多。

private static readonly string regexTest1 = @"(?((?=A))(A)|(\w))";
        private static readonly string regexTest2 = @"(?x)
        (?        # If ...
        ((?=A))   # next character is A
        (A)|      # Capture in group 1, else ...
        (\w))     # Capture in group 2 (and EndIf).
        ";

        static void Main(string[] args)
        {
            Match m1 = new Regex(regexTest1).Match("A");
            Match m2 = new Regex(regexTest2).Match("A");  // Exception!
        }

尝试使用regexTest 2时,程序出现“token not recognized”异常。看起来是条件语句“(?”和后面三行的结束括号导致了这个问题,但是为什么不能将它们分成几行呢?
作为一种变通方法,我使用了这样的连接字符串...

private static readonly string regexTest2 =
@"(?"          // If ...
+@"((?=A))"    // next character is A
+@"(A)|"       // Capture in group 1, else ...
+@"(\w))";     // Capture in group 2 (and EndIf).

但是我发现@和“”太分散了正则表达式部分的注意力。在.NET中,用这种方法拆分正则表达式有什么限制?还有其他(更清楚的)方法吗?

mzmfm0qo

mzmfm0qo1#

看起来(?在它自己的行上给解析器带来了问题。我不知道为什么,但是它 * 相当 * 容易解决。我个人会使用显式的RegexOptions而不是(?x),但是两者都有效:

using System.Text.RegularExpressions;

string pattern = @"
(?((?=A)) # If next character is A
(A)|      # Capture in group 1, else ...
(\w))     # Capture in group 2 (and EndIf).
";

Match match = new Regex(pattern, RegexOptions.IgnorePatternWhitespace).Match("A");

或者:

string pattern =
@"(?x)    # Ignore pattern whitespace
(?((?=A)) # If next character is A
(A)|      # Capture in group 1, else ...
(\w))     # Capture in group 2 (and EndIf).
";

Match match = new Regex(pattern).Match("A");

请注意,虽然这样写会更易读:

string pattern = @"
(?x) # Ignore pattern whitespace
...
";

......由于选项前的空格(换行符),它不会工作。它不会抛出异常(它是一个有效的正则表达式),但它不符合您的要求。
如果您确实希望将最外层的分组构造与第一个分组构造分开,可以给它一个名称:

using System.Text.RegularExpressions;

string pattern = @"
(?'outer' # If...
((?=A))   # next character is A
(A)|      # Capture in group 1, else ...
(\w))     # Capture in group 2 (and EndIf).
";

Match match = new Regex(pattern, RegexOptions.IgnorePatternWhitespace).Match("A");

相关问题