不跳过文本的正则表达式

Regular Expression That Doesn't Skip Over Text

我知道我的问题措辞不佳,但我想不出其他方式来表达它。假设我有以下文本,我想对其进行正则表达式匹配:

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

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

谢谢!

子模式 .*? 位于:

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

正在匹配应该忽略的中间 TAG1。所以我们需要匹配除<STARTTAG1>以外的任何字符。我们可以通过一种 loop 检查每个字符后面没有使用 negative lookahead.

的标签来实现这一点
(?:(?!<STARTTAG1>).)*?

这样,它会阻止该子模式匹配 middle 标签。然而,由于它现在失败了,正则表达式引擎将回溯,并且之前的子模式:

(?<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