不会跳过文本的正则表达式

时间:2015-11-06 05:52:59

标签: regex grouping matching

我知道我的问题措辞不是很好,但我无法想出另一种说法。想象一下,我有以下文字要进行正则表达式匹配:

Some random text here <STARTTAG1>text to match<ENDTAG1> some more 
random text <STARTTAG2>text to match<ENDTAG2>  more random text 
Some random text here <STARTTAG1>I don't want this text to match<ENDTAG1> some more 
random text more random text 
Some random text here <STARTTAG1>text to match<ENDTAG1> some more 
random text <STARTTAG2>text to match<ENDTAG2>  more random text 

这是我目前正在使用的正则表达式:

<STARTTAG1>(?<text1>.*?)<ENDTAG1>?.*?<STARTTAG2>(?<text2>.*?)<ENDTAG2>

如果在提供的文本上运行该正则表达式,则它与正确对中的文本不匹配。我希望它忽略任何STARTTAG1 / ENDTAG1匹配,如果他们在遇到另一个STARTTAG1 / ENDTAG1之前没有STARTTAG2 / ENDTAG2。

任何帮助将不胜感激。如果我的解释不是很好,请在文本上运行正则表达式,你就会明白我的意思(希望如此)。

谢谢!

1 个答案:

答案 0 :(得分:2)

子模式.*?位于:

<STARTTAG1>(?<text1>.*?)<ENDTAG1>?.*?<STARTTAG2>(?<text2>.*?)<ENDTAG2>
                                  ^ ^
                             here |_|

匹配应忽略的中间 TAG1。所以我们需要匹配除<STARTTAG1>之外的任何字符。我们可以通过一种循环来实现这一点。使用negative lookahead检查每个字符后面没有标记。

(?:(?!<STARTTAG1>).)*?

这样,它可以防止子模式与中间标记匹配。但是,由于它现在失败了,正则表达式引擎将回溯,以及之前的子模式:

(?<text1>.*?)

将尝试匹配文字:

I don't want this text to match<ENDTAG1> some more 
random text more random text 
Some random text here <STARTTAG1>text to match<ENDTAG1>

我们可以使用相同的方法,但我们也可以使用atomic group来阻止回溯。

(?><STARTTAG1>(?<text1>.*?)<ENDTAG1>)

<强>正则表达式

(?><STARTTAG1>(?<text1>.*?)<ENDTAG1>)(?:(?!<STARTTAG1>).)*?<STARTTAG2>(?<text2>.*?)<ENDTAG2>
  • 模式:全球+单线

regex101 demo