2017-08-11 130 views
5

我正在使用C#驗證網址的正則表達式。現在,我需要的正則表達式不能與其他http://匹配,但是它是url中的第一個。這是我第一次嘗試:懶惰量詞和向前看

(https?:\/\/.+?)\/(.+?)(?!https?:\/\/) 

但這正則表達式不工作(甚至消除(?!https?:\/\/))。就拿這個輸入字符串:

http://test.test/notwork.http://test 

這是我的第一個疑問:爲什麼不捕獲組(.+?)比賽notwork.http://test?懶惰的量詞應該儘可能少地匹配,但爲什麼不直到最後呢?在這種情況下,我肯定錯過了一些東西(首先我認爲它可能與回溯有關,但我不認爲是這種情況),所以我讀this並找到了解決方案,即使我不確定是否是最好的因爲它說,

該技術存在任何優勢來相會點星級

總之,該解決方案是回火點。這是我的下一個嘗試:

(https?:\/\/.+?)\/((?:(?!https?:\/\/).)*) 

現在:這個正則表達式工作,但不是我想要的方式。 只有當網址有效時,我才需要一個匹配。

順便說一句,我想我已經不能充分理解新的正則表達式是這樣做的:爲什麼負先行的.前停留,而不是之後呢? 所以我試圖在.之後移動它,它似乎匹配url直到找到第二個http之前的倒數第二個字符。回到正確的正則表達式,我的假設是負面的前瞻實際上是試圖檢查.已經讀過的正則表達式,這是正確的嗎?

其他解決方案已被廣泛接受,但我首先更願意理解這一點。謝謝。

+0

這個問題太廣泛了。第二個「懷疑」在[這裏]解釋(https://stackoverflow.com/questions/30900794/tempered-greedy-token-what-is-different-about-placing-the-dot-before-the-negat)。至於第一個,你只需要使用* positive * lookahead和''''替代('(。*?)(?= https?:\/\/| $)')。一個'。+?'匹配1個字符,並且不需要匹配更多,因爲它是懶惰的。 –

+0

你是什麼意思「只有當網址有效時我需要一個匹配」? –

+0

關於第一個疑問:我應該使用'$',這樣懶惰的量詞可以匹配直到輸入結束,對嗎?爲什麼沒有暗示?我讀到你的回答關於脾氣暴躁的標記*,它肯定更清楚。只有當url不包含其他'http://'時,我才需要一個匹配,而當我使用當前的正則表達式時,如果包含'http://',我也有匹配。順便說一句,謝謝你的答案。 –

回答

2

你所尋求的解決方案是

(?>https?://\S+?/(?:(?!https?://).)*)(?!https?://) 

regex demo

詳細

  • (?>https?://\S+?/(?:(?!https?://).)*) - 的原子團(允許無回溯到它的子模式)匹配
    • https?:// - http://https://
    • \S+? - 任何1個或多個非空白字符,儘可能少,直至第一...
    • / - /符號隨後與...
    • (?:(?!https?://).)* - 零個或多個字符(儘可能多),它們不會啓動一系列http://https://字符。
  • (?!https?://) - 負先行失敗的比賽,如果有http://https://立即到當前位置的右側。

(https?:\/\/.+?)\/(.+?)(?!https?:\/\/)因爲.+?圖案匹配懶惰地不工作,即它抓住它找到的第一個字符,然後讓後續子模式匹配。隨後的子模式是僅在當前位置右側沒有http://https://的情況下才失敗匹配的負面loolahead。由於在http://test.test/notwork.http://test中的n之後沒有這樣的子字符串,所以以n結尾的匹配被返回,所以匹配成功。如果您不告訴正則表達式引擎匹配更多,或者直到其他分隔符/模式,它不會。

脾氣暴躁的標記解決方案已被討論了很多。 this answer中涵蓋了確切的懷疑在何處放置預覽。