2013-10-07 73 views

回答

3

有趣的問題!

就與此發揮各地,並想出了以下內容:

val r = ("\"" + "(?:[^\"\\p{Cntrl}\\\\]*|(?:\\\\(?:[\\\\'\"bfnrt]|u[a-fA-F0-9]{4}))*)*" + "\"").r 

注:上述正則表達式是從第一個版本固定......無論是領先的「\」和拖尾字符需要重複一遍,不只是我原來的尾隨角色!

編輯:找到更有效的正則表達式。使用以下命令,它可以解析最多950 \\ns對的字符串,而不是隻能解析556的原始對象,至少在我的默認配置下是這樣。

val r = ("\"" + "(?:[^\"\\p{Cntrl}\\\\]*|\\\\[\\\\'\"bfnrt]|\\\\u[a-fA-F0-9]{4})*" + "\"").r 

編輯2:基於從@schmmd的評論,我有一個更好的正則表達式。這可以解析酷刑案件。祕訣是使用貪婪的佔有慾修飾符,這基本上禁止了回溯的需要,因此也關閉了遞歸。

val r = (""""([^"\p{Cntrl}\\]*+(?:\\[\\'"bfnrt])*+(?:\\u[a-fA-F0-9]{4})*+)*+"""").r 

解決方案的精髓在於每次匹配某件東西時儘可能地嘗試和咀嚼。

scala> val r = (""""([^"\p{Cntrl}\\]*+(?:\\[\\'"bfnrt])*+(?:\\u[a-fA-F0-9]{4})*+)*+"""").r 
r: scala.util.matching.Regex = "([^"\p{Cntrl}\\]*+(?:\\[\\'"bfnrt])*+(?:\\u[a-fA-F0-9]{4})*+)*+" 

scala> r.pattern.matcher("\"" + "\\ns" * 2500 + "\"").lookingAt 
res4: Boolean = true 

scala> r.pattern.matcher("\"" + "s" * 2500 + "\"").lookingAt 
res5: Boolean = true 

更新:一個pull request被提交給鄉親階。它被接受了。

+1

我希望Java有一個內置的正則表達式實現,使用湯普森NFA ... – schmmd

+0

您的正則表達式很好,但我有意義刪除所有的disjunctions。它仍然會在你的''\\ ns「* 2500'上溢出。 '(「\」「+」「」([^「\ p {Cntrl} \\] *(?:\\ [\\''bfnrt])*(?:\\ u [a-fA-F0- 9] {4})*)*「」「+」\「」)。r'。 – schmmd

+0

將我所有的Kleene星星轉換爲所有格Kleene星星提供更好的性能。 (「\」「+」「」([^「\ p {Cntrl} \\] * +(?:\\ [\\''bfnrt])* +(?:\\ u [a-fA-F0 -9] {4})* +)* +「」「+」\「」)。r – schmmd