2015-07-21 1260 views
2

當我嘗試調用crossUI(一個js框架)的函數來rtrim文本內容是grep通過jQuery,Firefox和Chrome會遇到繁忙。 我在源代碼中發現這個正則表達式阻止了瀏覽器。 我試過/[\s\uFEFF\xA0]+$/,它的工作原理。 爲什麼/(\s|\uFEFF|\xA0)+$/卡住了?他們之間有什麼內在的不同?

$('body').text().replace(/(\s|\uFEFF|\xA0)+$/, ""); 
 
alert('pass');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> 
 
<div> 
 
    <div>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div> 
 
    <div>a</div> 
 
</div>

+0

那麼,方括號之一是一個字符類,其中'|'包含兩次...所以它也將刪除所有垂直條。 – Xufox

+0

@Xufox Thx,我修復了代碼 – Junyo

+1

這似乎是[災難性回溯]的另一種情況(http://www.regular-expressions.info/catastrophic.html)。這也可以通過RegEx的簡單示例看到:['((::\s|\s)+$/'](https://regex101.com/r/fM1lY7/1)。 – Xufox

回答

3

一個字符集/[aa]/相當於/[a]/:這是一組,假定每一個元素只能出現一次(和額外的項被忽略)。這一切都行得通,因爲每個選項只有一個字符 - 沒有出現複雜問題的空間。

但是,如果發生故障,需要檢查每個分支的變更/(a|a)/,以防萬一,因爲它不能保證一個分支對另一個分支的決定不會產生任何後果。交替不保證固定寬度,它不保證捕獲組的不變等。在這種情況下,是的,兩個分支是相同的;但正則表達式引擎不檢查這一點。

因此,如果你有/[aa]+$/,並在覈查aaaaX,你有四項檢查,每一個字符,匹配失敗由於非結束stringness前 - 一樣/[a]+$/(實際上相同爲/a+$/)。但對於/(a|a)+$/,您有2 * (1 + 2 * (1 + 2 * (1 + 2)))檢查,總共有三十個,因爲每個分支都被檢查。對於字符串中的每個額外的a,由於引擎需要檢查a分支以及a分支(!)以查看它們中的一個奇蹟般地設法匹配,所以您的時間加倍。

因此,將此應用於您的問題。如評論中所述,您在一個分支中有\xA0,並且它也隱含在\s中;因此/(\s|\uFEFF|\xA0)+$/將在每個&nbsp;上執行時間加倍,而您在白色空間序列中的執行時間不在字符串末尾。 (真正的rtrim部分,即被替換的部分,並不構成問題 - 字符串空白序列的結束沒有任何延遲地完成,因爲第一個測試分支(全部爲\s)成功並且不回溯。)

3

根據ECMA 5.1 specification\s包括WhiteSpaceLineTerminator,和空白符包括U + FEFF和U + 00A0在其定義中。

一個簡單的測試

/^\s+$/.test("\ufeff\u00a0") 

表明IE9和Firefox的最新版本(38)和鉻(43)如下的那些2個字符的規格。如果您決定放棄對舊瀏覽器的支持,則不需要手動將這些字符添加到正則表達式中。只需使用\s

如果需要支持他們在舊的瀏覽器,包括他們在一個字符類:

[\s\ufeff\u00a0] 

交替使用會引起ECMA 5.1兼容的瀏覽器災難性的回溯。由於交替創建了回溯的選擇點和\s與ECMA 5.1中的U + 00A0匹配,\s\xA0\s|\uFEFF|\xA0中提供了兩個有效的選項以匹配一個非中斷空間。當你有一串連續的空格時(按照\s的定義),你將會有O(2 n)的情況來檢查,其中n是上述子字符串中沒有空格的數量。這同樣適用於\ufeff,但這種角色大量出現的情況更爲罕見。

相反,角色類不會創建回溯的選擇點,所以在新舊瀏覽器中都可以安全使用。

從技術上講,允許引擎將問題中的變化重寫爲字符類。然而,這在實踐中並不常見,因爲它會使發動機的實施複雜化。