在java中使用Regex格式化字符串,如何将捕获的组转换为特殊字符?

时间:2015-06-03 03:56:16

标签: java regex unicode special-characters

我有一组包含隐藏字符的命令,写在文本文件中。他们一个接一个地读取并发送服务器来执行命令。

正确格式化特殊字符非常重要,但是它们不能简单地以"\u0002"的形式写入文本文件中,因为它将被解释为"\u0002",而不是<STX>。 1}}我正在寻找的角色。

因此,我所做的就是以这种格式将它们写在文本文件中:

$'\x02'test$'\x03'

我在java中编写了一个正则表达式来提取数值,如下所示:

"\\$'\\\\x(\w\w)'". 

(注意额外的转义字符,以逃避$\

我的问题是:我如何获取十六进制字符(\w\w),然后将它们转换为字符串中的Unicode字符,理想情况下使用String.format?

我知道我可以使用"$1"来物理抓取角色,因为"(\w\w)"是每个正则表达式模式中的第一个也是唯一的一个组。但是,我遇到转换问题。我尝试了以下内容:

String.replaceAll("\\$'\\\\x(\w\w)'",
Character.toString((char)Integer.parseInt("$1")));

但我遇到了Integer.parseInt("$1")部分的问题,因为$1被解释为字符串"$1",而不是被捕获的组(例如,02)。

作为一种快速解决方法,我已针对每个需要的案例实施了一种解决方法。 (例如:String.replace("\\$'\\\\x(02)'", Character.toString((char) (int)0x0002)))。然而,这显然是一种可怕的形式,并且在解析任何情况下根本无效。

如果有人可以帮助我,并指出我的文档/解释为什么$1被解释为"$1"而不是被捕获的群组,以及解决方案/解决方法,那将会很多赞赏。

编辑:

感谢下面的nhahtdh。他的回答是正确的,尽管我做了一个小修改:

    static String handleEscape(String input) {

    Pattern p = Pattern.compile("\\$'\\\\x(\\w\\w)'");
    Matcher m = p.matcher(input);

    StringBuffer result = new StringBuffer();

    while (m.find()) {
        m.appendReplacement(result, Character.toString((char) Integer.valueOf(m.group(1), 16)));
    }

    m.appendTail(result);

    return result.toString();
}

我将Integer.parseInt(m.group(1))更改为Integer.valueOf(m.group(1), 16),以便将任何正确的字符串正确转换为关联的十六进制值。

1 个答案:

答案 0 :(得分:1)

由于您需要在替换之前操作匹配的文本,因此您需要使用Matcher类中的低级API来手动执行匹配和替换。

static String handleEscape(String input) {

    Pattern p = Pattern.compile("\\$'\\\\x(\\w\\w)'");
    Matcher m = p.matcher(input);

    StringBuffer result = new StringBuffer();

    while (m.find()) {
        m.appendReplacement(result,
            Character.toString((char) Integer.parseInt(m.group(1), 16)));
    }

    m.appendTail(result);

    return result.toString();
}