(注意:以下使用的是JavaScript风格的RegExen,其中。与换行符不匹配,但[^]匹配。)
想象一下我有这段文字:chaff more chaff START PATTERN more chaffchaff more chaff START PATTERN juicy stuffjuicy stuff juicy stuff END PATTERN chaffchaff START PATTERN more juicy stuff morejuicy stuff END PATTERN
...,我想要一个带有全局标志(g)的RegEx来捕获多汁的东西。具体来说,我希望第一场比赛是START PATTERN juicy stuffjuicy stuff juicy stuff END PATTERN
第二场比赛是START PATTERN more juicy stuff morejuicy stuff END PATTERN
美中不足的是第一个开始模式。我已经在regex101.com(对那些不了解它的人来说是一个了不起的工具)上度过了一段时间,但是这个方法不起作用:
/(?:START PATTERN[^]+)?(START PATTERN[^]+END PATTERN)/?
它捕获了第二组(“多汁的东西”),但没有捕获第一组。我还尝试过各种否定先行组合,但均未成功。
有想法吗?
最佳答案
您需要一个tempered greedy token:
START PATTERN(?:(?!(?:START|END) PATTERN)[^])*END PATTERN
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
参见the regex demo。
(?:(?!(?:START|END) PATTERN)[^])*
称为经过调节的贪婪 token ,因为贪婪的*
量词以负前瞻方式进行调节。在前瞻内部,我们列出了所有我们不希望与尾随定界符匹配的模式。请注意,如果您计划匹配文字单词
START
和END
,则可以通过添加单词边界来提高精度:\bSTART PATTERN\b(?:(?!\b(?:START|END) PATTERN)[^])*\bEND PATTERN
请注意,为提高效率,我们可以展开它:
START PATTERN[^ES]*(?:S(?!TART PATTERN)[^ES]*|E(?!ND PATTERN)[^ES]*)*END PATTERN
参见another demo