2014-06-25 81 views
4

我試圖捕捉特定單詞前的網址。唯一的麻煩是這個詞也可能是該領域的一部分。正則表達式:先捕獲第一個匹配項

例子:(我試圖捕捉晚餐前的所有內容)

 
https://breakfast.example.com/lunch/dinner/ 

https://breakfast.example.brunch.com:8080/lunch/dinner 

http://dinnerdemo.example.com/dinner/ 

我可以使用:

^(.*://.*/)(?=dinner/?)

我有被超前不會出現麻煩由懶足夠 所以下面的失敗:

 
https://breakfast.example.com/lunch/dinner/login.html?returnURL=https://breakfast.example.com/lunch/dinner/ 

,因爲它捕捉:

https://breakfast.example.com/lunch/dinner/login.html?returnURL=https://breakfast.example.com/lunch/

我都不明白爲什麼以及如何修復我的正則表達式。 也許我在錯誤的軌道上,但我如何捕獲我所有的例子?

+0

你用什麼語言? –

回答

4

你可以使用一些懶惰:

^(.*?:\/\/).*?/(?=dinner/?) 

Live demo

通過在您的正則表達式,你什麼都吃,直到最後一個冒號,在那裏找到了匹配的中間使用.*

.*在正則表達式中,順便​​說一下,這是非常糟糕的做法。它會導致長字符串中可怕的回溯性能下降。 .*?更好,因爲它不願意而不是貪婪。

4

向前看並不一定是懶惰或不是,向前看只是一個支票,在你的情況下與準固定字符串。

你需要做什麼的懶惰顯然是前瞻的子模式。

^https?:\/\/(?:[^\/]+\/)*?(?=dinner(?:\/|$)) 

注:(?:/|$)就是這樣確保單詞「晚餐」之後斜線或字符串的結束邊界。

1

您的主要缺陷是使用貪婪匹配.*與非貪婪.*?

以下執行您希望使用perl的匹配,但正則表達式可以很容易地應用於任何語言。注意周圍吃飯用字邊界,這可能會或可能不是你想要的是:

use strict; 
use warnings; 

while (<DATA>) { 
    if (m{^(.*?://.*?/.*?)(?=\bdinner\b)}) { 
     print $1, "\n"; 
    } 
} 

__DATA__ 
https://breakfast.example.com/lunch/dinner/ 
https://breakfast.example.brunch.com:8080/lunch/dinner 
http://dinnerdemo.example.com/dinner/ 

輸出:

https://breakfast.example.com/lunch/ 
https://breakfast.example.brunch.com:8080/lunch/ 
http://dinnerdemo.example.com/ 
1

另一種方式爲好。

# Multi-line optional 
# ^(?:(?!://).)*://[^?/\r\n]+/(?:(?!dinner)[^?/\r\n]+/)*(?=dinner) 


^     # BOL 
(?: 
     (?! ://) 
     . 
)* 
:// 
[^?/\r\n]+   # Domain 
/ 
(?: 
     (?! dinner) # Dirs ? 
     [^?/\r\n]+ 
    /   
)* 
(?= dinner) 

https://breakfast.example.com/lunch/晚餐/

https://breakfast.example.brunch.com:8080/lunch/晚餐

http://dinnerdemo.example.com/晚餐/

https://breakfast.example.com/lunch/晚餐/ login.html的?RETURNURL = https://breakfast.example.com/lunch/dinner/

相關問題