Problème intéressant !!
Juste joué avec cela, et est venu avec les éléments suivants:
val r = ("\"" + "(?:[^\"\\p{Cntrl}\\\\]*|(?:\\\\(?:[\\\\'\"bfnrt]|u[a-fA-F0-9]{4}))*)*" + "\"").r
Note: l'expression rationnelle ci-dessus a été fixé de la première version ... à la fois le premier « \ » et les caractères de fin doivent être répété, pas seulement les caractères finaux comme je l'avais à l'origine!
Editer: Trouvé une expression régulière plus efficace. En utilisant ce qui suit, il peut analyser une chaîne de jusqu'à 950 paires \\ns
, par opposition à l'original qui ne pouvait analyser que 556, au moins dans ma configuration par défaut.
val r = ("\"" + "(?:[^\"\\p{Cntrl}\\\\]*|\\\\[\\\\'\"bfnrt]|\\\\u[a-fA-F0-9]{4})*" + "\"").r
Edit 2: Basé sur le commentaire de @schmmd, j'ai une expression régulière encore mieux. Celui-ci peut analyser le cas de torture 2500 \ns
. Le secret est d'utiliser le modificateur possessive avide, cela annule fondamentalement le besoin de revenir en arrière, et donc aussi éteint la récursivité.
val r = (""""([^"\p{Cntrl}\\]*+(?:\\[\\'"bfnrt])*+(?:\\u[a-fA-F0-9]{4})*+)*+"""").r
L'essence de la solution est d'essayer de mâcher autant que vous le pouvez chaque fois que vous faites correspondre quelque chose.
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
Mise à jour: Unpull request a été présenté aux gens de scala. Et c'était accepté.
Je souhaite que Java ait une implémentation regex intégrée qui utilise les NFA de Thompson ... – schmmd
Votre regex va bien, mais il est logique pour moi d'enlever toutes les disjonctions. Il déborde toujours sur votre '' \\ ns "* 2500' cependant. '(" \ "" + "" "([^" \ p {Cntrl} \\] * (?: \\ [\\ '"bfnrt]) * (?: \\ u [a-fA-F0- 9] {4}) *) * "" "+" \ ""). R'. – schmmd
Passer toutes mes étoiles Kleene à des étoiles Kleene possessive offre une meilleure performance. ("\" "+" "" ([^ "\ p {Cntrl} \\] * + (?: \\ [\\ '" bfnrt]) * + (?: \\ u [a-fA-F0 -9] {4}) * +) * + "" "+" \ ""). R – schmmd