2014-05-08 43 views
3

這應該很簡單,但它讓我難以置信。有很多好的和壞的正則表達式方法來匹配一個URL,無論是否使用協議,使用或不使用www。我遇到的問題是這樣的(在JavaScript中):如果我使用正則表達式來匹配文本字符串中的URL,並將其設置爲只匹配'domain.com',它還會捕獲電子郵件地址的域'@'之後的部分),我不想要。一個負面的背後隱藏解決了它 - 但顯然不在JS中。正則表達式匹配domain.com,但不支持@ domain.com

這是迄今爲止我最近的成功:

/^(www\.)?([^@])([a-z]*\.)(com|net|edu|org)(\.au)?(\/\S*)?$/g 

但如果比賽是不是在字符串的開頭失敗。而且我相信我正在以錯誤的方式解決問題。那裏有一個簡單的答案嗎?

編輯:修正則表達式來幾個下面的評論作出迴應(孜孜以求的「www」,而不是讓子域:

\b(www\.)?([^@])(\w*\.)(\w{2,3})(\.\w{2,3})?(\/\S*)?$ 

正如但是評論中提到,這仍然域名之後匹配一個@。

感謝

+0

This [question](http://stackoverflow.com/questions/641407/javascript-negative-lookbehind-equivalent)* may * help。 – merlin2011

+5

備註:您是否知道有大量新TLD可用或即將可用? – Marty

+0

也許你可以通過http://regexr.com/ – HJ05

回答

0

經過大量的搞砸之後,這個結束了工作(用一個確定的帽子ti p來@ ZMO的最後評論):

var rx = /\b(www\.)?(\w*@)?([a-zA-Z\-]*\.)(com|org|net|edu|COM|ORG|NET|EDU)(\.au)?(\/\S*)?/g; 
var link = txt.match(rx); 
    if(link !== null) { 
    for(var i = 0; i < link.length; i++) { 
     if (link[i].indexOf('@') == -1) { 
     //create link 
     } else { 
     //create mailto; 
     } 
     } 
     } 

我知道的侷限性,對於子域,頂級域名等(其中@ ZMO上面已經解決了 - 如果你需要捕獲所有的網址,我建議你修改該代碼),但這不是我的情況中的主要問題。我的答案中的代碼允許匹配不帶「www。」的文本字符串中的網址,也不會捕獲電子郵件地址的域。

1

如果比賽不在字符串的開頭失敗

那是因爲^在比賽的開始:

/(www\.)?([^@])([a-z]*\.)(com|net|edu|org)(\.au)?(\/\S*)?$/g

js> "www.foobar.com".match(/(www\.)?([^@])([a-z]*\.)(com|net|edu|org)(\.au)?(\/\S*)?$/g) 
["www.foobar.com"] 
js> "aoeuaoeu foobar.com".match(/(www\.)?([^@])([a-z]*\.)(com|net|edu|org)(\.au)?(\/\S*)?$/g) 
[" foobar.com"] 
js> "[email protected] foobar.com".match(/(www\.)?([^@])([a-z]*\.)(com|net|edu|org)(\.au)?(\/\S*)?$/g) 
[" foobar.com"] 
js> "[email protected] [email protected]".match(/(www\.)?([^@])([a-z]*\.)(com|net|edu|org)(\.au)?(\/\S*)?$/g) 
["foobar.com"] 

雖然它仍然匹配域之前的空間。這是對域的錯誤假設...

  • xyz.example.org是與您的正則表達式不匹配的有效域;
  • www.3x4mpl3.org是與您的正則表達式不匹配的有效域;
  • example.co.uk是與您的正則表達式不匹配的有效域;
  • ουτοπία.δπθ.gr是與您的正則表達式不匹配的有效域。

什麼定義了合法域名?它只是由點分隔的一系列utf-8字符。它不能有兩個點,並且規範名稱是\w\.\w\w(因爲我不認爲一個字母tld存在)。

雖然,我會做的方式是簡單地匹配一切看起來像域,採取一切,是文本用點分隔使用單詞邊界(\b):

/\b(\w+\.)+\w+\b/g

js> "aoe toto.example.org uaoeu foo.bar aoeuaoeu".match(/\b(\w+\.)+\w+\b/g) 
["toto.example.org", "foo.bar"] 
js> "aoe [email protected] toto.example.org uaoeu foo.bar aoeuaoeu".match(/\b(\w+\.)+\w+\b/g) 
["example.org", "toto.example.org", "foo.bar"] 
js> "aoe [email protected] toto.example.org uaoeu foo.bar aoeuaoeu f00bar.com".match(/\b(\w+\.)+\w+\b/g) 
["example.org", "toto.example.org", "foo.bar", "f00bar.com"] 

然後進行第二輪檢查域是否確實存在或不在發現的域列表中。缺點是JavaScript中的正則表達式無法檢查unicode字符,並且\b\w將不接受ουτοπία.δπθ.gr作爲有效的域名。

在ES6,還有的/u modifier,這應與最新的瀏覽器中工作(但沒有,我迄今已檢測):

"ουτοπία.δπθ.gr aoe [email protected] toto.example.org uaoeu foo.bar aoeuaoeu".match(/\b(\w+\.)+\w+\b/gu) 

編輯:

負回顧後解決它 - 但顯然不在JS中。

是的,它會:跳過所有的電子郵件地址,這裏的落後執行正則表達式的工作看:

/(?![^@])?\b(\w+\.)+\w+\b/g

js> "aoe [email protected] toto.example.org uaoeu foo.bar aoeuaoeu f00bar.com".match(/(?<![^@])?\b(\w+\.)+\w+\b/g) 
["toto.example.org", "foo.bar", "f00bar.com"] 

儘管它同樣爲Unicode ...它」即將在那裏在JS很快...

唯一的方法就是,實際上保留@在匹配的正則表達式,並放棄任何匹配包含一個@:

js> "toto.net aoe [email protected] toto.example.org uaoeu foo.bar aoeuaoeu f00bar.com".match(/@?\b\w+\.+\w+\b/g).map(function (x) { if (!x.match(/@/)) return x }) 
["toto.net", (void 0), "toto.example", "foo.bar", "f00bar.com"] 

或使用來自ES6/JS1.7新的列表理解,這應該是沒有在現代瀏覽器...

[x for x of "toto.net aoe [email protected] toto.example.org uaoeu foo.bar aoeuaoeu f00bar.com".match(/@?\b\w+\.+\w+\b/g) if (!x.match(/@/))]; 

一個最後更新:

/@?\b(\w*[^\W\d]+\w*\.+)+[^\W\d_]{2,}\b/g

> "x.y tot.toc.toc $11.00 11.com 11foo.com toto.11 toto.net aoe [email protected] toto.example.org uaoeu foo.bar aoeuaoeu f00bar.com".match(/@?\b(\w*[^\W\d]+\w*\.+)+[^\W\d_]{2,}\b/g).filter(function (x) { if (!x.match(/@/)) return x }) 
[ 'tot.toc.toc', 
    '11foo.com', 
    'toto.net', 
    'toto.example.org', 
    'foo.bar', 
    'f00bar.com' ] 
+0

在regex101.com上驗證失敗,但似乎通過了Firebug。無論如何,我都會更新它,以防止它捕獲諸如「$ 1」之類的內容。(\ w \ 2,3})(\/\)(\ w {2,3}) S *)\ b/g標準;'。如果我將它放在我的電子郵件匹配代碼之前,它仍然匹配域,然後電子郵件匹配失敗。如果我在電子郵件匹配後匹配URL,它可以工作,但它似乎做了很多工作,因爲它匹配文本和mailto href。至少一切正常。所以,我不確定這是否是答案。無論如何,謝謝。 – sideroxylon

+1

好吧,您應該匹配電子郵件和fqdn,然後將電子郵件過濾到您的電子郵件轉換代碼,並將域轉換爲域轉換代碼。這會讓事情變得更簡單。儘管www開始一個域名是錯誤的。但是一個域不能只有數字,它至少需要一個字母。無論如何,只有一種標準的方式來測試域名:它實際上是針對DNS註冊表進行檢查。 – zmo

+0

添加了一個正則表達式,它僅基於數字tld或僅數字域或一個字符tld刪除無效域。 – zmo