• Java基础(二十六):正则表达式



    一、正则表达式语法

    灵活地运用正则表达式,必须了解各种元字符的功能,以下分成:

    1. 限定符
    2. 选择匹配符
    3. 分组组合和反向引用符
    4. 特殊字符
    5. 字符匹配符
    6. 定位符

    1.1 理解分组的概念与matcher.group(i)的联系?

    1. 捕获分组
    在这里插入图片描述

    public static void main(String[] args) {
            String content = "在1998年12月11日到2004年2月12日";
    
            System.out.println("-------一、捕获分组---------");
    
            System.out.println("------------1.非命名分组()--------");
            String regStr = "(\\d\\d)(\\d)(\\d)";
            Pattern pattern = Pattern.compile(regStr);
            Matcher matcher = pattern.matcher(content);
            while(matcher.find()){
                System.out.println("第一个字符串"+matcher.group(0));
                System.out.println("第一组()"+matcher.group(1));
                System.out.println("第二组()"+matcher.group(2));
                System.out.println("第三组()"+matcher.group(3));
            }
    
            System.out.println("--------2.命名分组(?)----------");
            String regStr1 = "(?\\d\\d)(?\\d\\d)";
            Pattern pattern1 = Pattern.compile(regStr1);
            Matcher matcher1 = pattern1.matcher(content);
            while(matcher1.find()){
                System.out.println("第一个字符串"+matcher1.group(0));
                System.out.println("第一组"+matcher1.group("g1"));
                System.out.println("第二组"+matcher1.group("g2"));
            }
        }
    输出:
    -------一、捕获分组---------
    ------------1.非命名分组()--------
    第一个字符串1998
    第一组()19
    第二组()9
    第三组()8
    第一个字符串2004
    第一组()20
    第二组()0
    第三组()4
    --------2.命名分组(?<name>)----------
    第一个字符串1998
    第一组19
    第二组98
    第一个字符串2004
    第一组20
    第二组04
    
    • 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

    2. 非捕获分组:不能使用matcher.group(i) 当i>=1
    在这里插入图片描述

    System.out.println("-------二、非捕获分组---------");
            String content01 = "hello韩顺平教育 jack韩顺平老师 韩顺平同学hello";
    
            // 目标:找到 韩顺平教育 韩顺平老师 韩顺平同学
            System.out.println("-----(?:)------");
            String regstr01 = "韩顺平(?:教育|老师|同学)";
            Pattern pattern01 = Pattern.compile(regstr01);
            Matcher matcher01 = pattern01.matcher(content01);
            while(matcher01.find()){
                System.out.println(matcher01.group(0));
            }
    
            // 目标:找到 韩顺平教育 韩顺平老师 中的韩顺平
            System.out.println("-----(?=)------");
            String regstr02 = "韩顺平(?=教育|老师)";
            Pattern pattern02 = Pattern.compile(regstr02);
            Matcher matcher02 = pattern02.matcher(content01);
            while(matcher02.find()){
                System.out.println(matcher02.group(0));
            }
    
            // 目标:找到除了 韩顺平教育 韩顺平老师 中的韩顺平
            System.out.println("-----(?!)------");
            String regstr03 = "韩顺平(?!教育|老师)";
            Pattern pattern03 = Pattern.compile(regstr03);
            Matcher matcher03 = pattern03.matcher(content01);
            while(matcher03.find()){
                System.out.println(matcher03.group(0));
            }
    
    输出:
    -------二、非捕获分组---------
    -----(?:)------
    韩顺平教育
    韩顺平老师
    韩顺平同学
    -----(?=)------
    韩顺平
    韩顺平
    -----(?!)------
    韩顺平
    
    • 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

    1.2 转义字符 \ \

    在Java中用" \ \ “表示其他语言的 ’ \ ',比如要找“abc$(abc(123(”里面的‘(’,表达式为” \ \ ( "
    注意:如果你想要的符号写在[]里面,就不用加\\,例如:上面表达式也可以写成 " [(] "

    1.3 字符匹配符

    在这里插入图片描述
    在这里插入图片描述
    这里修正和补充一下:
    \ \ w表示匹配单个 数字、大小写字母、下划线
    \ \ s匹配任意空白字符(空格,制表符等);
    \ \ S匹配任意非空白字符
    . 表示匹配除\n的所有字符。

    1.4 选择匹配符 |

    @Test
        public void method03(){
            String content = "abca 11c8Abc 李";
            // 使用 | 选择匹配符找到abc A 李 任意一个
            String regStr = "abc|A|李";
            Pattern pattern = Pattern.compile(regStr);
            Matcher matcher = pattern.matcher(content);
            while(matcher.find()){
                System.out.println(matcher.group(0));
            }
        }
    输出:
    abc
    A
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    1.5 限定符

    限定符就是要限定匹配字符的个数
    在这里插入图片描述
    在这里插入图片描述
    补充一下:abc{3}表示匹配adccc。 a{3,4}表示匹配aaa或者aaaa,但是优先匹配4个a【贪婪匹配】
    综合一下:以上所有限定符都会满足贪婪匹配,优先匹配最大范围的结果

    1.6 定位符

    定位符就是规定匹配字符串出现的位置,比如指定在字符串开始还是结束的位置

    在这里插入图片描述

    1.7 贪婪匹配和非贪婪匹配

    贪婪匹配,优先匹配最大范围的结果;非贪婪匹配则与之相反,下面演示一下:
    所有正则式默认都是贪婪匹配,非贪婪匹配只需在语句后面加上?

    public void method04(){
            String content = "abccca 11c8Abc 李";
            String regStr1 = "\\d+"; // 贪婪匹配
            Pattern pattern = Pattern.compile(regStr1);
            Matcher matcher = pattern.matcher(content);
            System.out.println("贪婪匹配:");
            while(matcher.find()){
                System.out.println(matcher.group(0));
            }
    
            String regStr2 = "\\d+?"; // 非贪婪匹配
            Pattern pattern2 = Pattern.compile(regStr2);
            Matcher matcher2 = pattern2.matcher(content);
            System.out.println("非贪婪匹配:");
            while(matcher2.find()){
                System.out.println(matcher2.group(0));
            }
        }
    
    结果:
    贪婪匹配:
    11
    8
    非贪婪匹配:
    1
    1
    8
    
    • 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

    1.8 应用实例

    package RegularExpression;
    
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    /**
     * @author 神代言
     * @version 1.0
     */
    public class RegExpExercise {
        public static void main(String[] args) {
            // 1.汉字:
            // 解释:^起始位置,$结束为止,
            // String content = "一万年可长否";
            // String regStr = "^[\u0391-\uffe5]+$";
    
            // 2.邮政编码要求:1-9开头的一个六位数
            // String regStr = "^[1-9]\\d{5}$";
    
            // 3.QQ号码要求:1-9开头的一个5-10位数
            // String regStr = "^[1-9]\\d{4,9}$";
    
            // 4.手机号码:要求13、14、15、18开头的11位数
            // String regStr = "^1[3|4|5|8]\\d{9}$";
    
            // 5.验证URL:
            String content = "https://www.bilibili.com/video/BV1fh411y7R8/?p=894" +
                    "&spm_id_from=pageDriver&vd_source=b6cd1b2cafcf0b55448eb890ac82becf";
            // 第一部分验证:https://
            // 第二部分验证:www.bilibili.com
            // 第三部分验证:/video/BV1fh411y7R8/?p=894&spm_id_from=pageDriver&vd_source=b6cd1b2cafcf0b55448eb890ac82becf
            String regStr = "^((http|https)://)" + "([\\w-]+\\.)+[\\w-]+"
                     + "(/[\\w-?=&/%.]*)?$";
            Pattern pattern = Pattern.compile(regStr);
            Matcher matcher = pattern.matcher(content);
            if(matcher.find()){
                System.out.println("验证成功");
            }
        }
    }
    
    • 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

    二、如何设置不区分大小写

    这里演示在指定字符串中找到不区分大小的“abc”

    public void method02(){
            String content = "abca11c8Abc";
            String regStr = "abc";
            // Java默认区分大小写,这里演示如何不区分大小写
            // 方式一:regStr =
            //     (?i)abc 表示abc不区分大小写
            //     a(?i)bc 表示bc不区分大小写
            //     a((?i)b)c 表示b不区分大小写
            // 方式二:Pattern.compile(regStr,Pattern.CASE_INSENSITIVE);
            Pattern pattern = Pattern.compile(regStr,Pattern.CASE_INSENSITIVE);
            Matcher matcher = pattern.matcher(content);
            while(matcher.find()){
                System.out.println(matcher.group(0));
            }
        }
    
    输出:
    abc
    Abc
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    三、Pattern类

    在这里插入图片描述

    3.1 整体匹配

    public class PatternMethod {
        public static void main(String[] args) {
            String content = "hello abc hello, 韩顺平教育";
            //String regStr = "hello abc hello, 韩顺平教育";  // -> true
            String regStr = "hello.*";  // -> true
    
            boolean matches = Pattern.matches(regStr, content);
            System.out.println("整体匹配= " + matches);
            // 一般使用使用整体匹配验证字符串是否满足规则
            // Pattern.matches(regStr, content)
            // 成功返回true
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    四、Matcher类

    在这里插入图片描述

    package RegularExpression;
    
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    /**
     * @author 神代言
     * @version 1.0
     */
    public class MatcherMethod {
        public static void main(String[] args) {
            String content = "hello edu jack hspedutom hello smith hello hspedu hspedu";
            String regStr = "hello";
    
            Pattern pattern = Pattern.compile(regStr);
            Matcher matcher = pattern.matcher(content);
            while (matcher.find()) {
                System.out.println("=================");
                System.out.println(matcher.start());
                System.out.println(matcher.end());
                System.out.println("找到: " + content.substring(matcher.start(), matcher.end()));
            }
    
            //整体匹配方法,常用于,去校验某个字符串是否满足某个规则
            System.out.println("整体匹配=" + matcher.matches());
    
            //完成如果content 有 hspedu 替换成 韩顺平教育
            regStr = "hspedu";
            pattern = Pattern.compile(regStr);
            matcher = pattern.matcher(content);
            //注意:返回的字符串才是替换后的字符串 原来的 content 不变化
            String newContent = matcher.replaceAll("韩顺平教育");
            System.out.println("newContent=" + newContent);
            System.out.println("content=" + content);
        }
    }
    
    • 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

    五、分组、捕获和反向引用

    在这里插入图片描述
    案例

    public class RegExp01 {
        public static void main(String[] args) {
    
            String content = "h1234el9876lo33333 j12324-333999111a1551ck14 tom11 jack22 yyy12345 xxx";
            //要匹配两个连续的相同数字 :  (\\d)\\1
            //String regStr = "(\\d)\\1";
            //要匹配五个连续的相同数字: (\\d)\\1{4}
            //String regStr = "(\\d)\\1{4}";
            //要匹配个位与千位相同,十位与百位相同的数 5225 , 1551  (\\d)(\\d)\\2\\1
            //String regStr = "(\\d)(\\d)\\2\\1";
    
            /**
             * 请在字符串中检索商品编号,形式如:12321-333999111 这样的号码,
             * 要求满足前面是一个五位数,然后一个-号,然后是一个九位数,连续的每三位要相同
             */
            String regStr = "\\d{5}-(\\d)\\1{2}(\\d)\\2{2}(\\d)\\3{2}";
            Pattern pattern = Pattern.compile(regStr);
            Matcher matcher = pattern.matcher(content);
            while (matcher.find()) {
                System.out.println("找到 " + matcher.group(0));
            }
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    实例:经典的结巴程序

    public class RegExp02 {
        public static void main(String[] args) {
            String content = "我....我要....学学学学....编程java!";
            // 去掉重复的句子,将上面编程:我要学编程Java!
            //1. 去掉所有的.
    
            Pattern pattern = Pattern.compile("\\.");
            Matcher matcher = pattern.matcher(content);
            content = matcher.replaceAll("");
    
            //       System.out.println("content=" + content);
    
            //2. 去掉重复的字  我我要学学学学编程java!
            // 思路
            //(1) 使用 (.)\\1+
            //(2) 使用 反向引用$1 来替换匹配到的内容
            // 注意:因为正则表达式变化,所以需要重置 matcher
            pattern = Pattern.compile("(.)\\1+");//分组的捕获内容记录到$1
            matcher = pattern.matcher(content);
            while (matcher.find()) {
                System.out.println("找到=" + matcher.group(0));
            }
    
            //使用 反向引用$1 来替换匹配到的内容
            content = matcher.replaceAll("$1");
            System.out.println("content=" + content);
    
            //3. 使用一条语句 去掉重复的字  我我要学学学学编程java!
    //        content = Pattern.compile("(.)\\1+").matcher(content).replaceAll("$1");
    //        System.out.println("content=" + content);
        }
    }
    
    • 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

    六、String类中的关于正则表达式的常用功能

    6.1 替换功能

    public class RegExp03 {
        public static void main(String[] args) {
            String content = "2000年5月,JDK1.3、JDK1.4和J2SE1.3相继发布,几周后其" +
                    "获得了Apple公司Mac OS X的工业标准的支持。2001年9月24日,J2EE1.3发" +
                    "布。" +
                    "2002年2月26日,J2SE1.4发布。自此Java的计算能力有了大幅提升";
    
            //使用正则表达式方式,将 JDK1.3 和 JDK1.4 替换成JDK
            content = content.replaceAll("JDK1\\.3|JDK1\\.4", "JDK");
            System.out.println(content);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    6.2 验证功能

    public static void main(String[] args) {
            // 验证功能:要求手机号必须138 139开头
            String content = "13888889999";
            if (content.matches("1(38|39)\\d{8}")) {
                System.out.println("验证成功");
            } else {
                System.out.println("验证失败");
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    6.3 分割功能

    public static void main(String[] args) {
            // 分割功能:
            // 要求按照 # 或者 - 或者 ~ 或者 数字 来分割
            System.out.println("===================");
            content = "hello#abc-jack12smith~北京";
            String[] split = content.split("#|-|~|\\d+");
            for (String s : split) {
                System.out.println(s);
            }
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    特别说明
    本文章是个人整理的学习笔记,参考b站韩顺平老师的课程(【零基础 快速学Java】韩顺平 零基础30天学会Java)。老师讲的非常好,有兴趣的可以去看一下。

  • 相关阅读:
    ORACLE 查询SQL优化
    ERC721标准与加密猫
    分布式系统第五讲:分布式事务及实现方案
    vmware: 磁盘加载问题导致,emergency mode: login incorrect 滚动打印
    文本分析:NLP 魔法!
    华为云CDN加速,带你畅游网络
    亚马逊的这个Bug居然要花两个月时间来解决?
    《痞子衡嵌入式半月刊》 第 49 期
    2年开发经验去面试,吊打面试官,即将面试的程序员这些笔记建议复习
    2022.9.1 SAP RFC
  • 原文地址:https://blog.csdn.net/shendaiyan/article/details/132942567