2015-01-05 53 views
3

所以我寫了這個正則表達式驗證電子郵件地址:JS正則表達式凍結我的瀏覽器(S)

(?=^([A-Za-z\xC0-\xFF0-9\!\#\$\%\&\'\*\+\-\/\=\?\^\\_\`\{\|\}\~]\.?){0,63}[A-Za-z\xC0-\xFF0-9\!\#\$\%\&\'\*\+\-\/\=\?\^\\_\`\{\|\}\~]@[A-Za-z\xC0-\xFF0-9]([A-Za-z\xC0-\xFF0-9-]{0,61}[A-Za-z\xC0-\xFF0-9])?(\.[A-Za-z\xC0-\xFF]([A-Za-z\xC0-\xFF0-9-]{0,61}[A-Za-z\xC0-\xFF0-9])?)*$)(?=^.{3,254}$) 

,我想測試它在JS控制檯:

var patt = new RegExp("(?=^([A-Za-z\xC0-\xFF0-9\!\#\$\%\&\'\*\+\-\/\=\?\^\\_\`\{\|\}\~]\.?){0,63}[A-Za-z\xC0-\xFF0-9\!\#\$\%\&\'\*\+\-\/\=\?\^\\_\`\{\|\}\~]@[A-Za-z\xC0-\xFF0-9]([A-Za-z\xC0-\xFF0-9-]{0,61}[A-Za-z\xC0-\xFF0-9])?(\.[A-Za-z\xC0-\xFF]([A-Za-z\xC0-\xFF0-9-]{0,61}[A-Za-z\xC0-\xFF0-9])?)*$)(?=^.{3,254}$)") 

patt.test("[email protected]in.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domain.domai") 

即可以凍結我的標籤。較短的地址似乎工作正常。

使用C#和在線正則表達式工具(例如regex101.com)進行測試沒有任何問題。 發生了什麼事? JavaScript Regex引擎是否發生故障,還是僅僅是我的Regex?

(我知道這可能不是一個完美的電子郵件驗證,但這個問題是關於爲什麼沒有工作)

+3

使用正則表達式的文字語法,而不是正則表達式的構造後,它將支持。 – Pointy

+3

http://www.regular-expressions.info/catastrophic。html – Dalorzo

+3

問題的災難性回溯來自'(\。[A-Za-z \ xC0- \ xFF]?)*' - 似乎'?'(以及前一個'?')應該是'+'。 – Ryan

回答

1

使用正則表達式文字而不是RegExp的構造函數:

/(?=^(?:[A-Za-z0-9_\xC0-\xFF!#$%&'*+\/=?^`{|}~\\-]\.?){0,63}[A-Za-z0-9_\xC0-\xFF!#$%&'*+\/=?^`{|}~\\-]@[A-Za-z0-9\xC0-\xFF](?:[A-Za-z0-9\xC0-\xFF-]{0,61}[A-Za-z0-9\xC0-\xFF])?(?:\.[A-Za-z\xC0-\xFF](?:[A-Za-z0-9\xC0-\xFF-]{0,61}[A-Za-z0-9\xC0-\xFF])?)*$)(?=^.{3,254}$)/ 

我已經冒着在字符類中去除過度逃跑的自由(在JavaScript中,只有],\需要轉義,^如果不在字符類的開始處不需要轉義,-不需要轉義,如果它是在角色課程結束時)和使所有的捕獲組不捕獲(因爲你不關心捕獲的內容)。

當您使用RegExp構造函數時,您需要提供一個字符串。您需要轉義\以便在字符串文字中指定它;否則,它將被視爲字符串中的轉義序列,並且\將不會到達RegExp構造函數。

您可以將您的字符串複製並粘貼到瀏覽器控制檯的RegExp構造函數中。在Firefox 34.0:

"(?=^([A-Za-z\xC0-\xFF0-9\!\#\$\%\&\'\*\+\-\/\=\?\^\\_\`\{\|\}\~]\.?){0,63}[A-Za-z\xC0-\xFF0-9\!\#\$\%\&\'\*\+\-\/\=\?\^\\_\`\{\|\}\~]@[A-Za-z\xC0-\xFF0-9]([A-Za-z\xC0-\xFF0-9-]{0,61}[A-Za-z\xC0-\xFF0-9])?(\.[A-Za-z\xC0-\xFF]([A-Za-z\xC0-\xFF0-9-]{0,61}[A-Za-z\xC0-\xFF0-9])?)*$)(?=^.{3,254}$)" 
>>> "(?=^([A-Za-zÀ-ÿ0-9!#$%&'*+-/=?^\_`{|}~].?){0,63}[A-Za-zÀ-ÿ0-9!#$%&'*+-/=?^\_`{|}~]@[A-Za-zÀ-ÿ0-9]([A-Za-zÀ-ÿ0-9-]{0,61}[A-Za-zÀ-ÿ0-9])?(.[A-Za-zÀ-ÿ]([A-Za-zÀ-ÿ0-9-]{0,61}[A-Za-zÀ-ÿ0-9])?)*$)(?=^.{3,254}$)" 

雖然不是對於大多數部件,+-/形成字符範圍中的字符類,它包括,.(不旨在是在類字符)的問題。而你得到的點都.,而不是字面點,這是災難性的回溯這裏的原因:

(.[A-Za-zÀ-ÿ]([A-Za-zÀ-ÿ0-9-]{0,61}[A-Za-zÀ-ÿ0-9])?)* 

基礎上的正則表達式上面的文字,使用正則表達式構造函數的等效代碼爲:

new RegExp("(?=^(?:[A-Za-z0-9_\xC0-\xFF!#$%&'*+/=?^`{|}~\\\\-]\\.?){0,63}[A-Za-z0-9_\xC0-\xFF!#$%&'*+/=?^`{|}~\\\\-]@[A-Za-z0-9\xC0-\xFF](?:[A-Za-z0-9\xC0-\xFF-]{0,61}[A-Za-z0-9\xC0-\xFF])?(?:\\.[A-Za-z\xC0-\xFF](?:[A-Za-z0-9\xC0-\xFF-]{0,61}[A-Za-z0-9\xC0-\xFF])?)*$)(?=^.{3,254}$)") 

請注意,與RegExp文字相比,所有\都翻了一番。

雖然沒有理由使用RegExp構造函數。它只能用於需要基於某些輸入生成正則表達式的情況。固定正則表達式應指定爲RegExp文字。

+0

謝謝,這工作,並回答我的問題。看起來我還有更多的學習要做。 – JakeDiscBrake

0

你可以使用這個。 [點] 2,3字符作爲 每個域

var email_filter = /^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/; 
if (email_filter.test('[email protected]')) { 
    alert('Email is valid'); 
}