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

文章目录

  • 一、正则表达式语法
    • 1.1 理解分组的概念与matcher.group(i)的联系?
    • 1.2 转义字符 \ \
    • 1.3 字符匹配符
    • 1.4 选择匹配符 |
    • 1.5 限定符
    • 1.6 定位符
    • 1.7 贪婪匹配和非贪婪匹配
    • 1.8 应用实例
  • 二、如何设置不区分大小写
  • 三、Pattern类
    • 3.1 整体匹配
  • 四、Matcher类
  • 五、分组、捕获和反向引用
  • 六、String类中的关于正则表达式的常用功能
    • 6.1 替换功能
    • 6.2 验证功能
    • 6.3 分割功能


一、正则表达式语法

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

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

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

1. 捕获分组
Java基础(二十六):正则表达式_第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

2. 非捕获分组:不能使用matcher.group(i) 当i>=1
Java基础(二十六):正则表达式_第2张图片

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 转义字符 \ \

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

1.3 字符匹配符

Java基础(二十六):正则表达式_第3张图片
Java基础(二十六):正则表达式_第4张图片
这里修正和补充一下:
\ \ 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.5 限定符

限定符就是要限定匹配字符的个数
Java基础(二十六):正则表达式_第5张图片
Java基础(二十六):正则表达式_第6张图片
补充一下:abc{3}表示匹配adccc。 a{3,4}表示匹配aaa或者aaaa,但是优先匹配4个a【贪婪匹配】
综合一下:以上所有限定符都会满足贪婪匹配,优先匹配最大范围的结果

1.6 定位符

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

Java基础(二十六):正则表达式_第7张图片

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.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("验证成功");
        }
    }
}

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

这里演示在指定字符串中找到不区分大小的“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

三、Pattern类

Java基础(二十六):正则表达式_第8张图片

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
    }
}

四、Matcher类

Java基础(二十六):正则表达式_第9张图片

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);
    }
}

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

Java基础(二十六):正则表达式_第10张图片
案例

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));
        }

    }
}

实例:经典的结巴程序

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);
    }
}

六、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);
    }
}

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("验证失败");
        }
    }

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);
        }

    }

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

你可能感兴趣的:(Java基础,java,正则表达式)