RegexOptions.IgnorePatternWhitespace和group的命名,括号后不允许空白?

时间:2013-12-03 14:11:41

标签: c# .net regex whitespace

请查看以下代码,如果您愿意(或LINQPad),可以在ideone中进行测试:

void Main()
{
    var options = RegexOptions.IgnorePatternWhitespace;
    var reWorks       = new Regex(@"(?<a>)", options);
    var reDoesNotWork = new Regex(@"( ?<a>)", options);
}

我认为选项RegexOptions.IgnorePatternWhitespace应该允许两者都有效:

  

IgnorePatternWhitespace
  从模式中消除未转义的空白区域,并启用标有#的注释。但是,IgnorePatternWhitespace值不会影响或消除字符类中的空格。

(我强调指出我觉得应该涵盖这个案例的部分)

然而,似乎组的命名(以及可能的其他序列)确实需要与组左括号相邻,因此我得到了这个例外:

  

的ArgumentException
  解析&#34;(?)&#34; - 量词{x,y}无效。

这是文档中的错误,代码中的错误(即Regex的实现),还是我在这里没有正确理解的其他内容?

当我有效地尝试编写以下正则表达式代码来记录未来维护者的正则表达式时,我发现了这一点:

var Regex = new Regex(@"
    ...
    (
       ?<var1>          # group for first variable
       ...
    )

我不得不改变它:

var Regex = new Regex(@"
    ...
    (?<var1>            # group for first variable
       ...
    )

1 个答案:

答案 0 :(得分:1)

这不是一个异象,如果用正确的术语,它实际上很简单。

通过这个来陪我......

在Regex中,你有很多不同的令牌。

例如,这些是每个令牌:A[)^

此外,还有一些字符类标记,例如\w,它会计算为[a-zA-Z0-9_]之类的实际字符类,这只是一个较长的标记列表。

任何令牌之间都可以存在空格。但是,正如我刚才所说,一些令牌是独立的,有些是令牌结构,例如{1,200}这是一个长结构。

在不知道正则表达式引擎的情况下,您假设字符串是字符串解析的,也许第一步是执行以下操作:

String.Replace(Input, WhiteSpace, "")

但是在应用我们都知道的知识时,这会打破我们在这个正则表达式中的模式TWICE:

ABCD[ ]EFGH\ IJKL

是的,IgnoreWhiteSpace允许使用字符类中的空格,以及使用反斜杠进行转义时。

现在想象这个令牌被正则表达式引擎解析:.{ 2,3}首先解析Dot,然后打开Curly Bracket ......然后正则表达式引擎声明“我是一个重复阵列!!”下一个字符是最小重复数。空白符?那不是数字!!!断裂。

现在想象一下:( ?>Blah)。首先,解析(,然后正则表达式引擎检查下一个字符以查看此子表达式是否具有特殊功能,并找到WhiteSpace。 不!,这不是特殊功能子表达式。下一个令牌:WhiteSpace。 忽略WhiteSpace。下一个令牌:QuestionMark。 Preceding Token应该是可选的!...没有前面的字符,我们看到的最后一件事就是打开一个Sub-Expression ... wtf? BREAK

长话短说:使用多字符标记或令牌结构时,不应该使用WhiteSpace进行分解。在开始时没有移除空白区域,当Token Parser到达时,该桥被交叉。因此,如果Parser在令牌结构中获得了一个合适的时间,那么它会中断或者是不期望的结果。

你不能指望像String.Replace(Input, WhiteSpace, "")这样的东西成为Regex Token Parsing Engine的一部分。这会打破这么多代码。