关于反斜杠问题记录

关于反斜杠问题记录


在一次偶然测试中, 发现了一个关于反斜杠的小问题, 因对此类特殊字符,平常使用较少,所以花了一些时间去解决问题, 并且觉得此问题比较有趣, 故整理记录一下,方便后续解决同类问题.

一 问题引入

在一些特殊的应用场景中,需要对数据进行过滤,将一些非法的字符进行拦截,过滤,替换等等, 常见的场景如一些敏感的词语过滤,比如一些游戏ID等不允许特殊词语和字符等,甚至应用在某些项目为防止xss攻击等.

如下Demo案例展示, 要求将请求参数即reqStr字符串中的特殊字符替换为空字符串, 以防止特殊字符污染源数据.

public class Demo {

    /**
     * 常见的特殊字符
     */
    private static String[] specialStr = new String[]{"/", "\\" };

    /**
     * 测试字符
     */
    private static String reqStr = "123456/\\";

    /**
    将特殊字符转换成空字符串
    */
    @Test
    public void test1() {
        for (String str : specialStr) {
            if (reqStr.indexOf(str) > -1) {
                reqStr = reqStr.replaceAll(str, "");
            }
        }
        System.out.println(reqStr);
    }
    
    // 运行结果 : java.util.regex.PatternSyntaxException: Unexpected internal error near index 1
\
}

上述test1方法, 会报错 java.util.regex.PatternSyntaxException: Unexpected internal error near index 1 \

上述测试方法,会抛出异常,主要是正则表达式内部解析异常. 从代码上看, 可能以为没有问题, 但实际得从String提供的replaceAll方法看起.

String部分代码:

public String replaceAll(String regex, String replacement) {
        return Pattern.compile(regex).matcher(this).replaceAll(replacement);
    }

从代码中可知, replaceAll方法的第一个入参, 实际上是一个正则表达式. 根据debug结果发现, 是反斜杠替换过程中, 抛出正则转换异常.初步怀疑, 是正则表达式中 反斜杠的表示问题. 查询相关资料后,得知,在正则表达式中, 两个反斜杠表示一个反斜杠.

结合replaceAll方法,根据反推法, 如果我们要对反斜杠进行替换, 那么传入的正则regex必须是两个反斜杠(根据正则规定可知),再倒推到字符串中, 字符串中使用两个反斜杠表示一个反斜杠, 所以字符串regex必须是四个反斜杠.

根据上述可知:

  • 字符串中 两个反斜杠表示一个反斜杠 -> 用\\ 表示\
  • 正则中 四个反斜杠表示一个反斜杠 -> 用\\\\表示\

二 解决方法

针对字符串中反斜杠和正则表达式中反斜杠分开表示, 即字符串中反斜杠使用两个反斜杠表示(\\),而正则表达式中反斜杠使用四个反斜杠表示(\\\\)

public class Demo {

    /**
     * 常见的特殊字符
     */
    private static String[] specialStr = new String[]{"/", "\\" };

    /**
     * 测试字符
     */
    private static String reqStr = "123456/\\";

   /**
    将特殊字符转换成空字符串
    */
    @Test
    public void test2() {
        for (String str : specialStr) {
            int i = reqStr.indexOf(str);
            if (i > -1) {
                // 遇到单斜杠, 特殊处理
                if ("\\".equals(str)) {
                    reqStr = reqStr.replaceAll("\\\\", "");
                } else {
                    reqStr = reqStr.replaceAll(str, "");
                }
            }
        }
        System.out.println(reqStr);
    }
    // 运行结果: 123456
}

运行结果: 123456

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值