我正在尝试使用我在自由空间模式下制作的正则表达式,因此我可以添加注释并保持其可维护的未来。下面的程序是这个问题的一个示例,但是我遇到这个问题的实际正则表达式要复杂得多。
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!
}
尝试使用regexTest2时,程序出现"无法识别的令牌"中断。例外。似乎是条件句"(?’和再多三行的结束括号才是问题的根源,但为什么不能把它们分成几行呢?
作为一种工作,我使用像这样的连接字符串…
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中以这种方式分解正则表达式有什么限制?有没有别的(更清晰的)方式被我忽略了?
看起来(?
在它自己的行上会导致解析器出现问题。我不知道为什么,但是很容易解决。我个人会使用显式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");