[心得] 如何以糟糕的正規表示式使 nodejs, firefox, IE應接不暇

看板RegExp (正規表示式 Regular Expression)作者 (colorless)時間9年前 (2015/03/08 21:37), 編輯推噓2(209)
留言11則, 4人參與, 最新討論串1/1
二月底在做模板處理時,發現常常有 RegExp 卡住的狀況,之後發現有時是因為要跑很久。 在 node, firefox, IE 三大引擎上跑都一樣。 例如: '012345678901234567890123456789;'.match(/^(?:[^;]*)*$/) 用人腦計算,這式子顯然匹配不出結果;但電腦似乎還沒足夠聰明? 前面數字多添一點,跑出結果的時間會變長許多(呈天文數字成長?)。 看來只要 pattern 寫得糟一點,確實是可能讓 regular expression engine 掛掉不動的。 不過同樣的式子,perl 的 engine 似乎就比較聰明,馬上就跑出來了。 至於其 workaround,只好放棄一次完成,採用一個個 match。 以上例而言,就是一次次 .match(/^[^;]*/),並偵測是否從頭到尾都符合,直到完成。 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 1.173.96.149 ※ 文章網址: https://www.ptt.cc/bbs/RegExp/M.1425821856.A.FFF.html

03/08 23:41, , 1F
這是相當常見的 Catastrophic Backtracking 問題
03/08 23:41, 1F

03/09 00:14, , 2F
時間複雜度至少會是 Exponential time complexity
03/09 00:14, 2F

03/09 00:15, , 3F
而 Perl 的 RegExp 引擎,具備有上述問題的偵測能力
03/09 00:15, 3F

03/09 00:16, , 4F
可在 Perl script 內,第一行加入 use re 'debug';
03/09 00:16, 4F

03/09 00:17, , 5F
執行後可輕易觀察出其匹配的規則,以及錯誤偵測的方式
03/09 00:17, 5F

03/09 21:30, , 6F
感謝高手補充說明 :)
03/09 21:30, 6F

03/12 01:34, , 7F
以前學 compiler 的時候都只教最簡單的 DFA,感覺超有
03/12 01:34, 7F

03/12 01:35, , 8F
效率,但是後來才知道實際上在用的複雜多了
03/12 01:35, 8F

03/12 18:40, , 9F
DFA-based engine 不好寫, 而且碰到這種狀況狀態數會爆炸多
03/12 18:40, 9F

03/12 18:41, , 10F
(跟 NFA-based engine 的執行時間一樣是指數成長)
03/12 18:41, 10F

03/12 18:41, , 11F
某種程度上其實可以說 NFA based 拿時間換空間
03/12 18:41, 11F
文章代碼(AID): #1K_52W__ (RegExp)
文章代碼(AID): #1K_52W__ (RegExp)