正则表达式:ReplaceAllIn在生成UTF-8时返回StringIndexOutOfBoundsException

时间:2013-08-17 06:07:01

标签: regex scala unicode utf-8

我想替换所有出现的“\ uXXXX”类型的正则表达式,其中“XXXX”是  表示相应字符的Unicode字符的十六进制数。

我尝试了以下Scala代码:

def unscape(s : String) : String = {
 val rex = """\\u([0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z])""".r
 rex.replaceAllIn(s,m => {
     hex2str(m.group(1))
   }
}

def hex2str(s:String): String = {
  Integer.parseInt(s,16).toChar.toString  
}

如果我尝试,例如:

unscape("Hi\\u0024, \\u0024")

它给出了以下例外:

java.lang.StringIndexOutOfBoundsException: String index out of range: 1

this other question中,似乎Java处理Unicode字符可能存在错误。那是问题吗?

2 个答案:

答案 0 :(得分:2)

只是调整接受的答案:

  def unscape3(s: String): String = {
    val rex = """\\u(\p{XDigit}{4})""".r
    rex.replaceAllIn(s, m => Regex quoteReplacement hex2str(m group 1))
  }

  Console println unscape3("""Hi\u0024, \u0024""")

请注意,字符类是正确的,您在使用quoteReplacement时无需了解需要转义的内容。

(可能比多次扫描替换文字更有效。)

答案 1 :(得分:1)

请尝试以下操作:

def unscape(s: String): String = {
    val rex = """\\u([0-9a-fA-F]{4})""".r
    rex.replaceAllIn(s, m => {
        hex2str(m.group(1))
            .replaceAllLiterally("\\", "\\\\")
            .replaceAllLiterally("$", "\\$")
    })
}

根据replaceAllIn使用的Matcher.appendReplacement

  

请注意替换中的反斜杠(\)和美元符号($)   字符串可能会导致结果与正确的结果不同   作为文字替换字符串处理。可以对待美元符号   作为对如上所述的捕获的子序列的引用,和   反斜杠用于替换替换中的文字字符   字符串。