2012-11-30 91 views
7

我試圖匹配一些文本,如果它的附近沒有另一個文本塊。例如,如果"foo"不在其前面,我想匹配"bar"。我可以匹配"bar"如果"foo"立即先用它看負在身後這個表達式:使用通配符的正則表達式負反向

/(?<!foo)bar/ 

,但我也想不匹配"foo 12345 bar"。我嘗試過:

/(?<!foo.{1,10})bar/ 

但在Ruby中使用通配符+範圍似乎是無效的正則表達式。我在想這個問題是錯的嗎?

回答

9

您正在考慮正確的方法。但不幸的是,往後看往往是固定長度的。唯一的主要例外是.NET的正則表達式引擎,它允許在lookbehinds內部重複量詞。但是,既然你只需要一個負面的後視,而不是前瞻。有一個黑客給你。反轉字符串,然後嘗試匹配:

/rab(?!.{0,10}oof)/ 

然後扭轉比賽的結果或減去從字符串的長度匹配的位置,如果這是你所追求的。

現在來自你給出的正則表達式,我想這只是你實際需要的簡化版本。當然,如果bar本身就是一個複雜的模式,那麼需要進一步思考如何正確地反轉它。

請注意,如果您的模式需要可變長度lookbeheads和lookaheads,那麼解決此問題的難度就會更大。此外,你的情況,將有可能解構你回顧後分成多個可變長度的人(因爲你既不使用也不+*):

/(?<!foo)(?<!foo.)(?<!foo.{2})(?<!foo.{3})(?<!foo.{4})(?<!foo.{5})(?<!foo.{6})(?<!foo.{7})(?<!foo.{8})(?<!foo.{9})(?<!foo.{10})bar/ 

但是,這還不是所有的很好,是嗎?

+1

倒車字符串是一個有趣的想法。謝謝! –

3

正如m.buettner已經提到的,Ruby正則表達式中的lookbehind必須具有固定長度,並且在文檔中進行了描述。所以,你不能在後視範圍內放一個量詞。

您不需要在一個步驟中全部檢查。嘗試執行多個正則表達式匹配步驟來獲得你想要的。假設foobar斷條件的單個實例面前,不排除存在,無論是否有另一個bar,然後

string.match(/bar/) and !string.match(/foo.*bar/) 

會給你想要的東西的例子。

如果您更希望比賽與bar foo bar成功,那麼你就可以做到這一點

string.scan(/foo|bar/).first == "bar" 
+0

如果想法實際上檢索匹配,那麼這是有問題的。假設你有'bar foo bar'。 OP嘗試的正則表達式將檢索第一個「bar」。你的解決方案會聲稱沒有匹配。 (除了你省略了「最多10個字符」的啓發式) –

+0

@ m.buettner你和我對這個問題有不同的解釋。 – sawa

+1

當然。這就是爲什麼我不說你的解決方案是錯誤的。但是我認爲重要的是這樣的假設和差異是陳述的。因爲他們可能對OP或者將來發現這個問題的其他人不明顯。 –