正则表达式在一个输入块的中间捕获一个可选组

时间:2009-01-03 02:13:27

标签: .net regex

我遇到了一个似乎非常简单的RegEx问题,但我无法让它发挥作用。

假设我有这样的输入:

Some text %interestingbit% lots of random text lots and lots more %anotherinterestingbit%
Some text %interestingbit% lots of random text OPTIONAL_THING lots and lots more %anotherinterestingbit%
Some text %interestingbit% lots of random text lots and lots more %anotherinterestingbit%

输入中有很多重复块,在每个块中我想捕获一些总是存在的东西(%interestingbit%和%anotherinterestingbit%),但也有一些文本可能会或可能不会发生在 - 他们之间(OPTIONAL_THING),如果它在那里我想抓住它。

这样的RegEx只匹配其中包含OPTIONAL_THING的块(并且命名的捕获工作):

%interestingbit%.+?((?<OptionalCapture>OPTIONAL_THING)).+?%anotherinterestingbit%

所以看起来这只是让整个团队成为可选的问题,对吧?这就是我的尝试:

%interestingbit%.+?((?<OptionalCapture>OPTIONAL_THING))?.+?%anotherinterestingbit%

但是我发现虽然这匹配了所有3个块,但命名捕获(OptionalCapture)在所有这些块中都是空的!我如何让它工作?

请注意,每个块中可能有很多文本,包括换行符,这就是我输入“。+?”的原因。而不是更具体的东西。我正在使用.NET正则表达式,使用The Regulator进行测试。

3 个答案:

答案 0 :(得分:2)

我的想法与Niko的想法类似。但是,我建议放置第二个。+?在可选组内而不是第一个,如下所示:

%interestingbit%.+?(?:(?<optionalCapture>OPTIONAL_THING).+?)?%anotherinterestingbit%

这可以避免不必要的回溯。如果是第一个。+?在可选组内,并且搜索字符串中不存在OPTIONAL_THING,正则表达式在到达字符串末尾之前不会知道这一点。然后它需要回溯,或许相当多,以匹配%anotherinterestingbit%,正如你所说,它将永远存在。

此外,由于OPTIONAL_THING(如果存在)将始终位于%anotherinterestingbit%之前,因此它之后的文本也是有效可选的,并且更自然地适合可选组。

答案 1 :(得分:0)

为什么你有额外的括号?

试试这个:

%interestingbit%.+?(?<OptionalCapture>OPTIONAL_THING)?.+?%anotherinterestingbit%

或许这可行:

%interestingbit%.+?(?<OptionalCapture>OPTIONAL_THING|).+?%anotherinterestingbit%

在此示例中,该组捕获OPTIONAL_THING,或者不捕获任何内容。

答案 2 :(得分:0)

试试这个:

%interestingbit%(?:(.+)(?<optionalCapture>OPTIONAL_THING))?(.+?)%anotherinterestingbit%

首先是一个与.+OPTIONAL_THING匹配的非捕获组,或者没有。如果找到匹配项,则会在里面找到命名组,它会为您捕获OPTIONAL_THING。其余部分由.+?%anotherinterestingbit%捕获。

[edit]:我为其他捕获组添加了几个括号,所以现在捕获的组匹配以下内容:

  • $ 1:OPTIONAL_THING之前的文字或没有任何内容
  • $ 2或$ optionalCapture:OPTIONAL_THING或没有
  • $ 3:OPTIONAL_THING之后的文字,或者如果找不到OPTIONAL_THING,则%interestingbit%和%anotherinterestingbit%
  • 之间的全文

这些是您正在寻找的三场比赛吗?