Tola,复活了这个问题,因为它有一个相当简单的正则表达式解决方案,但没有提到。这个问题是这个问题中解释的“正则表达式匹配模式,不包括......”的技术的经典案例
这个想法是建立一个交替(一系列|
),其中左侧匹配我们不想要的东西,以便让它不碍事......然后匹配我们想要的|
东西,并捕获它到第 1 组。如果设置了第 1 组,您检索它并且您有一个匹配项。
那么我们不想要什么?
首先,如果和unwanted
之间存在,我们要消除整个外部块。你可以这样做:outer-start
inner-start
outer-start(?:(?!inner-start).)*?unwanted.*?outer-end
这将在第一个的左侧|
。它匹配整个外部块。
其次,如果和unwanted
之间存在,我们要消除整个外部块。你可以这样做:inner-end
outer-end
outer-start(?:(?!outer-end).)*?inner-end(?:(?!outer-end).)*?unwanted.*?outer-end
这将是中间|
。它看起来有点复杂,因为我们要确保“懒惰”*?
不会跳过块的末尾进入不同的块。
第三,我们匹配并捕获我们想要的东西。这是:
inner-start\s*(text-that-i-want)\s*inner-end
因此,在自由间距模式下,整个正则表达式是:
(?xs)
outer-start(?:(?!inner-start).)*?unwanted.*?outer-end # dont want this
| # OR (also don't want that)
outer-start(?:(?!outer-end).)*?inner-end(?:(?!outer-end).)*?unwanted.*?outer-end
| # OR capture what we want
inner-start\s*(text-that-i-want)\s*inner-end
在此演示中,查看右侧的第 1 组捕获:它包含我们想要的内容,并且仅适用于正确的块。
在 Perl 和 PCRE(例如在 PHP 中使用)中,您甚至不必查看第 1 组:您可以强制正则表达式跳过我们不想要的两个块。正则表达式变为:
(?xs)
(?: # non-capture group: the things we don't want
outer-start(?:(?!inner-start).)*?unwanted.*?outer-end # dont want this
| # OR (also don't want that)
outer-start(?:(?!outer-end).)*?inner-end(?:(?!outer-end).)*?unwanted.*?outer-end
)
(*SKIP)(*F) # we don't want this, so fail and skip
| # OR capture what we want
inner-start\s*\Ktext-that-i-want(?=\s*inner-end)
见演示:它直接匹配你想要的。
该技术在下面的问题和文章中进行了详细说明。
参考