背景:

要将字符串里的\0\9替换成$0$9,但是要考虑\被转义的情况,比如\\9是不能被替换的。

方式一

先将\\替换成不可能出现的字符:

    static void main(String[] args) {
        String str = "\\0\\0\\\\0\\9\\0abcdefg\\\\9abc\\0\\\\\\0\\9\\\\\\9";
        System.out.println(str);
        System.out.println(str.replaceAll("\\\\\\\\(0|9)", "不替换$1")
                .replaceAll("\\\\(0|9)", "\\$$1")
                .replaceAll("不替换", "\\\\\\\\"));
    }

其中不替换可以根据实际场景,改为其他不可能出现的字符

方式二

纯正则的方式:

    public static void main(String[] args) {
        String str = "\\0\\0\\\\0\\9\\0ab\\cdefg\\\\9abc\\0\\\\\\0\\0\\9\\\\\\9";
        System.out.println(str);
        System.out.println(str.replaceFirst("^\\\\(0|9)", "\\$$1")
                .replaceAll("([^\\\\])\\\\(0|9)", "$1\\$$2")
                // 必须两轮
                .replaceAll("([^\\\\])\\\\(0|9)", "$1\\$$2"));
    }

其中:

  • 使用非\ + \ + 0|9的方式,来排除掉\\0|9这种场景。
  • 上面的方案,由于靠\前是否还有\的方式来判断,所以要处理开头就是\0的场景。
  • 必须两轮replaceAll,否则会出现以下结果:
a\0\0\0\0\0\0

被替换成

a$0\0$0\0$0\0

因为java按正则规则,把字符串根据适配符合规则的串打散成以下几个串:a\0 + \ + 0\0 + \ + 0\0 + \0,其中a\0被替换成a$00\0被替换成0$0,其他的不替换。所以需要再replaceAll一轮。


noname
314 声望49 粉丝

一只菜狗