托拉,復活這個問題,因爲它有一個相當簡單的正則表達式的解決方案,沒有提到。這個問題是該技術的一個經典案例在這個問題解釋"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