• Java正则表达式正确,find()方法返回false,可能是因为\s无法匹配空格


    环境

    java:1.8+
    idea:2022.1.3

    前言

    今天发现了一个很奇怪的现象。
    在内容相同的情况下:

    1. 单元测试,读取文件的文本,正则表达式可以匹配。
    2. 响应流中读取的却无法匹配

    单元测试读取文本的方式,可以正常匹配

    @Test
    public void currentBase() {
        ClassPathResource resource = new ClassPathResource("/html/a.html");
        try {
            InputStream inputStream = resource.getInputStream();
            StringBuilder builder = TestUtil.getStringBuilderByInputStream(inputStream);
            CurrentStarBO bo = OService.currentBase(builder.toString());
            System.out.println(JSON.toJSONString(bo));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    
    public static StringBuilder getStringBuilderByInputStream(InputStream inputStream) throws IOException {
        byte[] inputByte = new byte[inputStream.available()];
        StringBuilder builder = new StringBuilder();
        //BufferedReader.readLine() 换行符不会被保留,导致格式不对,所以改用最原始的方式:InputStream.read()
        while (inputStream.read(inputByte) != -1) {
            String str = new String(inputByte, 0, inputByte.length, "gbk");
            builder.append(str);
        }
        return builder;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    响应流里读取的方式,却不可以匹配

    public static String parseResponse2(HttpResponse<InputStream> response) {
        if (response == null) {
            return null;
        }
        int statusCode = response.statusCode();
        if (statusCode != 200) {
            return null;
        }
        try {
            // 获取应答的所有头部属性
            HttpHeaders resHeaders = response.headers();
            //压缩方式
            String contentEncoding = resHeaders.firstValue("Content-Encoding").orElse(null);
            //内容类型
            String contentType = resHeaders.firstValue("Content-Type").orElse(null);
            if (contentType == null) {
                return null;
            }
            String[] split = contentType.split(";");
            String[] charsetArr = split[1].split("=");
            InputStream is;
            if (StringUtils.isNotBlank(contentEncoding) && contentEncoding.contains("gzip")) {
                is = new GZIPInputStream(response.body());
            } else {
                is = response.body();
            }
            // 打印HTTP调用的应答内容长度、内容类型、压缩方式
            System.out.printf("应答内容长度=%s, 内容类型=%s, 压缩方式=%s%n",
                    resHeaders.firstValue("Content-Length").orElse(null), contentType, contentEncoding);
            //BufferedReader.readLine() 换行符不会被保留,导致格式不对,所以改用最原始的方式:InputStream.read()
            StringBuilder builder = new StringBuilder();
            byte[] inputByte = new byte[is.available()];
            int i = 0, len;
            while ((len = is.read(inputByte)) != -1) {
                String str = new String(inputByte, 0, len, charsetArr[1]);
                builder.append(str);
                ++i;
            }
            is.close();
            System.out.println("读取了" + i + "次");
            return builder.toString();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    这种方式获取的字符串,再去匹配正则表达式,就不行。

    解决办法

    昨晚弄到凌晨半,都没有弄出来,早上起来后,又来研究了下后,解决了。
    如标题所说,我的正则表达式里是有\s用来匹配换行符的。

    原来的正则表达式:

    
    
    (\d.*?)div>td>\s?.*?
    (\d.*?)div>td>
    • 1
    • 2

    我们可以看到\s?.+?这句,本意是希望匹配换行符、空格符。
    参考网上资料,改为:
    修改后的正则表达式:

    (\d.*?)div>td>[\s|\u3000|\u0020\u00A0]*.*?
    (\d.*?)div>td>
    • 1

    这样就可以了。

    说明

    以下内容来自网上资料:

    为什么会出现这种情况,问题在于空格的种类:

    • 半角空格
      • \u0020
      • 英文半角空格具有换行的效果,会出现不期望的换行现象;
      • 可以通过正则表达式\s进行匹配
    • 全角空格
      • \u3000
      • 不可通过正则表达式\s进行匹配
    • 不间断空格
      • \u00A0
      • 主要用途用于禁止自动换行,在英文中主要用于避免类似**(100 KM)**这种文字被错误地分词排版成两行。
      • 不可通过正则表达式\s进行匹配

    可以看出,只有半角空格,才可以,其他类型的空格都不行。

    所以:

    我们就不要用\s匹配,直接用unicode编码匹配[\u3000|\u0020\u00A0]+

    参考地址:

    Java正则表达式正确,find()方法返回false,可能是因为\s无法匹配空格

    python 爬虫爬取内容时, \xa0 、 \u3000 的含义

  • 相关阅读:
    软件加密系统Themida应用程序保护指南(十):高级选项
    服务器部署测试环境回顾与改进建议
    Spring Boot 依赖注入实现原理
    win10换ubuntu
    web前端-JavaScript中的call、apply和bind方法(改变this指向)
    请假要组长和经理同时审批该怎么办?来看看工作流中的会签功能
    出租屋智能视频监控系统方案:全面保卫租客安全
    微积分在金融投资的应用
    新能源汽车三电系统上的VDA接口在操作空间有限时如何快速密封与连接
    Transformer学习
  • 原文地址:https://blog.csdn.net/u013066244/article/details/126686178