Scala - 不使用Apache解码Unicode字符串

3

我有一个字符串 "b\u00f4lovar",想知道是否可以在不使用Commons-lang的情况下进行反转义。目前这个方法能够工作,但是在某些环境中出现了问题,我希望能够最小化这些问题(例如:它在我的电脑上运行良好,但在生产环境中无法正常工作)。

StringEscapeUtils.unescapeJava(variables.getOrElse("name", ""))

没有使用Apache库,我该如何进行反转义?

提前感谢。


编写自己的程序来解析十六进制数字并生成字符。 - bmargulies
1个回答

3

只使用Unicode转义

如果您只想要反转义格式为\u0000的序列,那么可以通过单个正则表达式替换来轻松完成:

def unescapeUnicode(str: String): String =
  """\\u+([0-9a-fA-F]{4})""".r.replaceAllIn(str,
    m => Integer.parseInt(m.group(1), 16).toChar match {
      case '\\' => """\\"""
      case '$' => """\$"""
      case c => c.toString
    })

结果是

scala> unescapeUnicode("b\\u00f4lovar \\u30B7")
res1: String = bôlovar シ

我们必须单独处理字符$\,因为它们被java.util.regex.Matcher.appendReplacement方法视为特殊字符:

def wrongUnescape(str: String): String =
  """\\u([0-9a-fA-F]{4})""".r.replaceAllIn(str,
    m => Integer.parseInt(m.group(1), 16).toChar.toString)

scala> wrongUnescape("\\u00" + Integer.toString('$', 16))
java.lang.IllegalArgumentException: Illegal group reference: group index is missing
  at java.util.regex.Matcher.appendReplacement(Matcher.java:819)
  ... 46 elided

scala> wrongUnescape("\\u00" + Integer.toString('\\', 16))
java.lang.IllegalArgumentException: character to be escaped is missing
   at java.util.regex.Matcher.appendReplacement(Matcher.java:809)
   ... 46 elided

所有转义字符

Unicode字符转义有些特殊:它们不是字符串字面值的一部分,而是程序代码的一部分。有一个单独的阶段将unicode转义替换为字符:

scala> Integer.toString('a', 16)
res2: String = 61

scala> val \u0061 = "foo"
a: String = foo

scala> // first \u005c is replaced with a backslash, and then \t is replaced with a tab.
scala> "\u005ct"
res3: String = "    " 

在Scala库中有一个名为StringContext.treatEscapes的函数,它支持语言规范中的所有普通转义字符
因此,如果您想支持Unicode转义和所有常规的Scala转义,可以依次取消转义两者。
def unescape(str: String): String =
  StringContext.treatEscapes(unescapeUnicode(str))

scala> unescape("\\u0061\\n\\u0062")
res4: String =
a
b

scala> unescape("\\u005ct")
res5: String = "    "

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接