1

我试图弄清楚为什么当“单行”选项打开时,带有负前瞻的正则表达式会失败。

示例(简化):

<source>Test 1</source>
<source>Test 2</source>
<target>Result 2</target>
<source>Test 3</source>

这:

<source>(?!.*<source>)(.*?)</source>(?!\s*<target)

如果单行选项打开,将失败,如果单行选项关闭,则将工作。例如,这有效(禁用单行选项):

(?-s:<source>(?!.*<source>)(.*?)</source>(?!\s*<target))

我的理解是单行模式只允许点“。” 匹配新行,我不明白为什么它会影响上面的表达式。

谁能解释我在这里缺少什么?

:::::::::::::::::::::::

编辑: (?!.*) 是负面的展望,而不是捕获组。

 <source>(?!.*?<source>)(.*?)</source>(?!\s*<target)

如果单行模式打开,也会失败,所以看起来这不是一个贪婪问题。在正则表达式设计器(如 Expresso 或 Rad 正则表达式)中尝试:

单行关闭,它匹配(如预期):

<source>Test 1</source>    
<source>Test 3</source>

单线开:

<source>Test 3</source>

我不明白为什么它也不匹配第一个:它不包含第一个否定的向前看,所以它应该匹配表达式。

4

2 回答 2

2

它“失败”的原因是因为您似乎放错了负前瞻。

<source>(?!.*<source>)(.*?)</source>(?!\s*<target)
        ^^^^^^^^^^^^^^

现在,让我们考虑一下(?!.*<source>)这里做了什么:这是一个前瞻,表示该位置没有匹配项.*<source>

好吧,在单行模式下,.匹配所有内容。在匹配前两个之后,<source>实际上.*<source>!因此,前两个的负前瞻失败<source>

在最后一个<source>.*<source>不再匹配,所以负前瞻成功。该模式的其余部分也成功了,这就是为什么您只能进入<source>Test 3</source>单行模式。

于 2010-06-01T09:58:34.153 回答
2

我相信这就是您正在寻找的:

<source>((?:(?!</?source>).)*)</source>(?!\s*<target)

这个想法是你一次匹配每个字符,但只有在确保它不是</source>. 此外,通过添加/?前瞻,您不必使用非贪婪量词。

于 2010-06-01T12:46:20.080 回答