2008-10-22 42 views
3

我有以下的正則表達式,做了偉大的工作匹配的網址:問題有關URL驗證與正則表達式

((https?|ftp|gopher|telnet|file|notes|ms-help):((//)|(\\\\))+[\w\d:#@%/;$()~_?\+-=\\\.&]*)` 

但是,它並沒有前綴,即處理的URL。 stackoverflow.comwww.google.com不匹配。任何人都知道我可以修改這個正則表達式,不在乎是否有前綴?


編輯:我的問題太模糊了嗎?它是否需要更多細節?


(((https?|ftp|gopher|telnet|file|notes|ms-help):((//)|(\\\\)))?[\w\d:#@%/;$()~_?\+-=\\\.&]*) 

我加了()?圍繞像這樣的協議建議使用Vinko Vrsalovic,但現在正則表達式幾乎可以匹配任何字符串,只要它具有有效的URL字符即可。

我的這個實現是我有一個數據庫,我管理的內容,它有一個字段,要麼有純文本,電話號碼,URL或電子郵件地址。我正在尋找一種簡單的方法來驗證輸入,所以我可以正確格式化,即。爲網址/電子郵件創建定位標記,以及格式化電話號碼的方式,我如何在整個網站中格式化其他數字。有什麼建議麼?

+0

我必須補充,我並不是建議你真的這樣做,只是顯示你,這正則表達式是沒有這部分幾乎無用 – 2008-10-22 16:39:08

+0

什麼有效的均值在這種情況下?你必須猜測它是哪一個? – 2008-10-22 16:40:41

回答

-2

只需使用:

.* 

即匹配一切。

你想匹配的東西只是主機名,而不是URL(技術上)。

沒有可用於確定主機名的結構。 也許你可以尋找的東西,在「.COM」結束,但隨後你會錯過任何.co.uk,淨,.org等

編輯:

換句話說:如果您刪除要求URL類似的東西以一個協議開始,你不會有任何事情需要匹配。 根據您所使用的正則表達式是什麼在:

  1. 對待一切,一個URL
  2. 保持要求的協議
  3. 哈克檢查的主機名普通的結局(如:.com或.net .ORG )並接受你會錯過一些。
+0

你是說,以取代方括號中的內容。*? – Anders 2008-10-22 16:27:19

0

您的正則表達式匹配所有以這些協議之一開始的所有內容,包括很多不可能存在的URL,如果放鬆協議部分(使其成爲可選參數?),那麼您只需匹配幾乎一切,包括空字符串。

換句話說,它在匹配網址方面做得很好,因爲它幾乎匹配以http://,https://,ftp://等開頭的任何內容。那麼它也會匹配ftp:\\和ms-help://,但我們忽略它。

這可能是有道理的,這取決於實際使用情況,因爲白名單有效域的其他regexp方法變得不夠快速維護,但使協議部分可選無效。

一個例子(與地方放鬆協議部分):

>>> r = re.compile('(((https?|ftp|gopher|telnet|file|notes|ms-help):((//)|(\\\\))+)?[\w\d:#@%/;$()~_?\+-=\\\.&]*)') 
>>> r.search('oompaloompa_is_not_an_ur%&%%l').groups()[0] 
'oompaloompa_is_not_an_ur%&%%l' #Matches! 
>>> r.search('oompaloompa_isdfjakojfsdi.sdnioknfsdjknfsdjk.fsdnjkfnsdjknfsdjk').groups()[0] 
'oompaloompa_isdfjakojfsdi.sdnioknfsdjknfsdjk.fsdnjkfnsdjknfsdjk' #Matches! 
>>>        

鑑於你的編輯,我建議你要麼讓用戶選擇是什麼,他加入,增加了ENUM列,或者創建一個更簡單的正則表達式是至少要檢查一個點,除了有效的字符和一些常用的域。

第三種選擇,這將是很慢只有或使用時,URL驗證真的真的很重要實際上訪問的URL,就可以做一個HEAD請求,如果你沒有發現一臺主機的錯誤你知道這是無效的。對於電子郵件,您可以嘗試查看MX主機是否存在並打開端口25。如果兩者均失敗,則將爲純文本。 (我也不建議這樣)

0

您可以圍繞在括號中的前綴部分,匹配0或1次出現

(((https?|ftp|gopher|telnet|file|notes|ms-help):((//)|(\\\\))+)?

所以整個正則表達式將成爲

(((https?|ftp|gopher|telnet|file|notes|ms-help):((//)|(\\\\))+)?[\w\d:#@%/;$()~_?\+-=\\\.&]*)

問題在於它會匹配或多或少的任何單詞。例如「測試」也是一個匹配。

你打算使用那個正則表達式?你想驗證一個主機名或者你是否想要在一個段落中找到主機名?

1

下面的正則表達式來自精彩的Mastering Regular Expressions書。如果您不熟悉free spacing/comments mode,我建議您熟悉它。

\b 
# Match the leading part (proto://hostname, or just hostname) 
(
    # ftp://, http://, or https:// leading part 
    (ftp|https?)://[-\w]+(\.\w[-\w]*)+ 
    | 
    # or, try to find a hostname with our more specific sub-expression 
    (?i: [a-z0-9] (?:[-a-z0-9]*[a-z0-9])? \.)+ # sub domains 
    # Now ending .com, etc. For these, require lowercase 
    (?-i: com\b 
     | edu\b 
     | biz\b 
     | gov\b 
     | in(?:t|fo)\b # .int or .info 
     | mil\b 
     | net\b 
     | org\b 
     | name\b 
     | coop\b 
     | aero\b 
     | museum\b 
     | [a-z][a-z]\b # two-letter country codes 
    ) 
) 

# Allow an optional port number 
(: \d+)? 

# The rest of the URL is optional, and begins with/. . . 
(
    /
    # The rest are heuristics for what seems to work well 
    [^.!,?;"'<>()\[\]{}\s\x7F-\xFF]* 
    (?: 
     [.!,?]+ [^.!,?;"'<>()\[\]{}\s\x7F-\xFF]+ 
    )* 
)? 

爲了解釋這個簡單的正則表達式(一個完整的解釋拿到書) - 網址有一個或多個點分隔的部分與最終位的任何一個有限的列表,或兩個字母的國家代碼結尾(.UK。 fr ...)。此外,這些零件可能有任何字母數字字符或連字符「 - 」,但連字符可能不是零件的第一個或最後一個字符。然後可能會有一個端口號,然後是剩下的端口號。

從網站摘錄這個,去http://regex.info/listing.cgi?ed=3&p=207從第3版的207頁開始。

頁面顯示「版權所有©2008 Jeffrey Friedl」,所以我不確定使用的條件是什麼,但我希望如果你擁有這本書,你可以使用它,所以...我是希望我沒有違反將規則放在這裏。

1

如果你讀了URL規範(http://www.isi.edu/in-notes/rfc1738.txt)第5條,你會看到一個URL的語法是至少有:

scheme ':' schemepart 

其中方案1個或多個字符,schemepart爲0或更多的字符。因此,如果您沒有冒號,則沒有URL。

這就是說,/用戶/不關心他們是否給了你一個url,對他們來說,它看起來像一個。所以這裏是我所做的:

在驗證之前,如果沒有冒號,請預先安裝http://,然後通過任何你想要的驗證器運行它。這將任何合法的主機名(其中可能不包括域名信息,畢竟)到的東西,看起來像一個URL。

frob -> http://frob 

(幾乎)主機部分的唯一規則是它不能以數字開頭,如果它不包含點。現在,有應該具體方案,其中沒有因此給出的正則表達式的遠完成進行具體驗證。但是,規範遵從性可能不是您想要「驗證」的內容。因此在主機部分的DNS查詢可能是有用的,但除非你使用相同的解析器在相同的上下文爲您的用戶,它是不會在所有情況下工作。