托拉,复活这个问题,因为它有一个相当简单的正则表达式的解决方案,没有提到。这个问题是该技术的一个经典案例在这个问题解释"regex-match a pattern, excluding..."
的想法是建立一个交替(一系列|
),其中左右两侧比赛我们不是为了得到它想要做然后... |
的最后一面与我们想要的匹配,并将其捕获到组1.如果组1被设置,则检索它并且您有匹配。
那么我们不想要什么?
首先,我们想要消除整个外部区块,如果在outer-start
和inner-start
之间有unwanted
。
outer-start(?:(?!inner-start).)*?unwanted.*?outer-end
这将是第一个|
左:你可以做到这一点。它匹配整个外部块。
第二,如果在inner-end
和outer-end
之间有unwanted
,我们想要消除整个外部块。你可以这样做:
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
在this demo,看看右边的第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)
See demo:它直接匹配你想要什么。
该技术在下面的问题和文章中有详细的解释。
参考
究竟是你想做些什么? – Gumbo 2010-01-02 23:18:13