2010-12-01 43 views
8

我們都知道正確驗證電子郵件的正則表達式是quite complicated。然而,jQuery的驗證插件具有更短的正則表達式(貢獻的Scott Gonzalez,跨越只有幾行:爲什麼jQuery的電子郵件驗證正則表達式如此簡單?

/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]) 
+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)| 
((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21| 
[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f] 
|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)? 
(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d| 
[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])* 
([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]| 
[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]) 
([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]| 
[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/ 

爲什麼會這樣「簡單」相比,更知名的怪物?有一種情況下,一個正則表達式會失敗,另一個會成功(這些情況是否是有效或無效的電子郵件)?

+12

簡單不是我將用於該正則表達式的單詞;) – JaredPar 2010-12-01 02:02:43

+4

* Ahem *簡單?如果這個正則表達式很簡單,那麼你會把什麼歸類爲複雜的? – Alex 2010-12-01 02:03:34

+0

談論踩在只寫語言的領土... – Serguei 2010-12-01 02:05:16

回答

10

正則表達式是一個自定義的組合:

  • RFC 2234 ABNF
  • RFC 2396 URI通用語法
  • RFC 2616超文本傳輸​​協議(由RFC 3986 obseleted) - HTTP/1.1
  • RFC 2822 Internet郵件格式
  • RFC 3987 IRI
  • RFC 3986 URI通用語法

我寫了正在起草和RFC 5322不存在的正則表達式。如果您查看RFC的編寫順序,您將注意到在寫入Internet郵件格式後,IRI和URI的定義發生了變化。這意味着RFC 2822不支持當前的IRI定義。不幸的是,這不是一個簡單的任務,只需要替換定義,所以我必須從哪個RFC中選擇使用哪些定義。我也選擇了要刪除的內容(如對評論的支持)。

該正則表達式並不完全是手寫的。雖然我手動編寫了正則表達式的每個部分,但我編寫了「膠水」。來自RFC的每個定義都存儲在一個變量中,化合物定義利用存儲簡單定義的變量(@Walf:這就是爲什麼有這麼多子模式和ors)。

使事情複雜化,在jQuery驗證插件中使用的正則表達式的版本進一步修改,以解決spec-valid地址和用戶期望有效地址之間的差異。我不記得我做了什麼修改。我答應JörnZaefferer(驗證插件的作者),我會寫一個更新的腳本來生成正則表達式。新腳本將允許您指定您所做和不想支持的選項(必需的頂級域名,特定的頂級域名,IPv6,註釋,過時的定義,引用的本地名稱等)。那是5年前。我開始了一次,但從未完成。也許有一天我會。我至今託管在GitHub上:https://github.com/scottgonzalez/regex-builder

如果你想爲驗證郵件地址的正則表達式,我建議這包括在HTML5 specification以下的正則表達式:

/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-][email protected][a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/

如果您使用正則表達式生成器並關閉所有選項,你會得到類似的東西。但是我看了這一年已經過去了大約一年,所以我不記得有什麼不同。


我還想指出的是,在原來的問題的鏈接特別提到RFC 822雖然它的偉大,RFC 822先進的美國從阿帕網到互聯網ARPA,這是不完全的電流。互聯網在過去三十年取得了一些進展,並且這個RFC已經被兩次取代。我希望看到遵循最新標準的新工作。


UPDATE:

有朋友問我,爲什麼HTML5正則表達式不支持UTF-8。我從來沒有向Hixie詢問過這件事,但我認爲這是原因:儘管一些TLD在2000年開始支持IDN(國際域名),並且在2005年編寫了RFC 3987(IRI),但在2008年編寫RFC 5322它僅將33-90和94-126範圍內的字符列爲有效的dtext(允許在域文字中使用的字符)。 HTML5基於RFC 5322,因此沒有UTF-8支持。 RFC 5322沒有考慮IDN,這似乎很奇怪,但即使在2008年,IDN並沒有實際可用,但它是毫無價值的。直到2010年,ICANN才批准了第一批IDN。然而,即使在今天,如果你想使用IDN,你幾乎需要使用Punycode徹底銷燬你的域名,如果你真的想讓電子郵件和DNS等全球工作。

更新2:

更新HTML5正則表達式相匹配的更新的規範,該規範改變標籤長度範圍從255個字符到63個字符,如在RFC 1034 section 3.5指定。

1

這看起來不正確:Unicode是什麼?哪一個RFC可以證實這一點?

請參閱this answer以獲得正確的RFC5322驗證正則表達式。

相關問題