JAVA入门基础_从零开始的培训_JAVA中的正则表达式、处理文本的利器(五)

正则表达式

基本语法

public class RegExpTest {
    public static void main(String[] args) {
        // 1. 定义一个模板(正则表达式),示例中的正则表达式:表示匹配4个相连的数字
        String regex = "(\\d\\d)(\\d\\d)";
        Pattern pattern = Pattern.compile(regex);

        // 2. 创建需要被匹配的内容
        String content = "2022年,今天风和日丽,并且天气也不错1011,你喜欢5410的风景吗?";

        // 3. 获取到一个匹配器
        Matcher matcher = pattern.matcher(content);

        // 4. 循环获取内容,在正则表达式中,每2个小括号,代表一组,示例中有2组
        while (matcher.find()) {
            String result = matcher.group(0);
            System.out.println(result);
        }
    }
}

源码解析(基于上述代码)

Matcher.find()方法

// 4.1 Matcher.find()方法,若是匹配到了内容,则返回true,否则返回false,每2个小括号,代表一组,示例中有2组
// 接下来将会分析匹配到第一个字符串时,源码中所进行的操作,之后的以此类推。
    // 4.1.1 该方法会将匹配字符串的第一个元素的索引赋值给Matcher.groups[0]
            // 例如第一次匹配到2022,其中第一个元素的索引为0,那么就赋值为0

    // 4.1.2 将匹配到的第一个字符串的最后一个元素的索引+1赋值给Matcher.groups[1]
            // 例如第一次匹配到2022,最后一个元素的索引为3,那么就赋值为4

    // 4.1.3 将匹配字符串中的”第一组分组“的第一个元素的索引赋值给Matcher.groups[2]
            // 例如匹配到的字符串为2022,第一组为20,其中第一个元素的索引为0,因此赋值0

    // 4.1.4 将匹配字符串中的”第一组分组“的最后一个元素的索引 + 1赋值给Matcher.groups[3]
            // 例如匹配到的字符串为2022,第一组为20,其中最后一个元素的索引为1,因此赋值 1 + 1 = 2

    // 4.1.5 将匹配字符串中的”第二组分组“的第一个元素的索引赋值给Matcher.groups[4]
            // 例如匹配到的字符串为2022,第二组为22,其中第一个元素的索引为2,因此赋值2

    // 4.1.6 将匹配字符串中的”第二组分组“的最后一个元素的索引赋值给Matcher.groups[5]
            // 例如匹配到的字符串为2022,第二组为22,其中最后一个元素的索引为3,因此赋值 3 + 1 = 4

Matcher.group(int group)方法

// 5. 使用Matcher.group()方法来获取匹配到的字符串数据
    // 接下来将基于第一次匹配到字符串2022时进行分析
    // 5.1 当输入group(0)时,执行到getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString()
          //5.1.1 这个getSubSequence方法相当于substring方法,用于截取传递的content的数据
          //5.1.2 因此当传入0时,groups[group * 2] 相当于 0 * 2 = groups[0] = 0,
                 //  groups[group * 2 + 1] 相当于 0 * 2 + 1 = groups[1] = 4.

                 //  而substring方法又是包含头而不包含尾的,content.substring(0, 4),就能取出2022了呗

         // 5.2.3 因此当传入1时,groups[group * 2] 相当于 1 * 2 = groups[2] = 0,
                //  groups[group * 2 + 1] 相当于 1 * 2 + 1 = groups[3] = 2.

                //  就相当于content.substring(0, 2),就能取出第一组:20,接下来的就以此类推了
    // 5.2 结论
        // group(0) 取出的是匹配的字符串
        // group(1) 取出的是第匹配到的字符串的第一组子串
        // group(2) 取出的是第匹配到的字符串的第二组子串

/*  源码如下:

    if (first < 0)
        throw new IllegalStateException("No match found");
    if (group < 0 || group > groupCount())
        throw new IndexOutOfBoundsException("No group " + group);
    if ((groups[group*2] == -1) || (groups[group*2+1] == -1))
        return null;
    return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();
 */

二个常用类

Pattern(相当于一个正则表达式)

Pattern.compile()方法

// 1. &#x5B9A;&#x4E49;&#x4E00;&#x4E2A;&#x6A21;&#x677F;&#xFF08;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#xFF09;&#xFF0C;&#x793A;&#x4F8B;&#x4E2D;&#x7684;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#xFF1A;&#x8868;&#x793A;&#x5339;&#x914D;4&#x4E2A;&#x76F8;&#x8FDE;&#x7684;&#x6570;&#x5B57;
String regex = "(\\d\\d)(\\d\\d)";
Pattern pattern = Pattern.compile(regex);

Pattern.matches()方法

public class RegExp01 {
    public static void main(String[] args) {
        // 1. &#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x5B57;&#x7B26;&#x4E32;
        String content = "abc abcde abcdefg";

        // 2. &#x5B9A;&#x4E49;&#x4E00;&#x4E2A;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;
//        String regExp = "abc";
        String regExp = "abc.*"; // &#x8FD9;&#x4E2A;&#x53EF;&#x4EE5;&#x5339;&#x914D;&#x6574;&#x4E2A;&#x5B57;&#x7B26;&#x4E32;&#xFF0C;&#x6240;&#x4EE5;Pattern.matches(regExp, content);&#x4E3A;true

        // 3. &#x8FDB;&#x884C;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#x4E0E;&#x5B57;&#x7B26;&#x4E32;&#x7684;&#x6574;&#x4F53;&#x5339;&#x914D;&#xFF0C;&#x4E5F;&#x5C31;&#x662F;&#x770B;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#x80FD;&#x591F;&#x5339;&#x914D;&#x5B8C;&#x4E00;&#x6574;&#x4E2A;&#x5B57;&#x7B26;&#x4E32;&#x3002;
        boolean matches = Pattern.matches(regExp, content);

        // 4. &#x6267;&#x884C;&#x8F93;&#x51FA;&#x7ED3;&#x679C;&#xFF0C;&#x8FD9;&#x91CC;&#x4E3A;true
        System.out.println("&#x662F;&#x5426;&#x5B8C;&#x6574;&#x5339;&#x914D;&#x6574;&#x4E2A;&#x5B57;&#x7B26;&#x4E32;&#xFF1A;" + matches);
    }
}

Matcher(匹配)

// 2. &#x521B;&#x5EFA;&#x9700;&#x8981;&#x88AB;&#x5339;&#x914D;&#x7684;&#x5185;&#x5BB9;
String content = "2022&#x5E74;&#xFF0C;&#x4ECA;&#x5929;&#x98CE;&#x548C;&#x65E5;&#x4E3D;&#xFF0C;&#x5E76;&#x4E14;&#x5929;&#x6C14;&#x4E5F;&#x4E0D;&#x9519;1011&#xFF0C;&#x4F60;&#x559C;&#x6B22;5410&#x7684;&#x98CE;&#x666F;&#x5417;&#xFF1F;";

// 3. &#x83B7;&#x53D6;&#x5230;&#x4E00;&#x4E2A;&#x5339;&#x914D;&#x5668;
Matcher matcher = pattern.matcher(content);

元字符

JAVA中的转义字符以及需要转义的字符

  • JAVA中的转义字符为两个反斜杠: “\”
  • 需要转义的字符如下
  • 所有的括号,包括小括号、中括号、大括号: “() [] {}”
  • 所有的斜杠,包括正斜杠、反斜杠:”/ “
  • 所有的限定符,包括点、问号、加号、大括号(重复):”. ? + {}”
  • 还有一个美元符号跟一个异或符号: “$ ^”

字符匹配符

字符匹配符 作用 正则示例 匹配结果示例 [ ] 可接收的字符列表 “[qwtg]”:表示匹配qwtg中任意的一个字符 q、w、t、g [^ ] 不接收的字符列表 “[^qwtg]”:表示匹配除了qwtg以外的任意字符 a、e、y、d [-] 连字符、可以写[a-z]、[A-Z]、[1-9] “[A-Z]”:表示匹配大写字母A-Z中的任意一个字符 A、B、C、D、Z . 匹配除了\n以外的任意字符 “a..b”:匹配a开头,中间匹配2个除了\n的任意字符,b结尾 abcb、a%&b、a68b \d 匹配数字,等价于[1-9] “\d”:表示匹配任意一个数字 8、9、5、1、2 \D 匹配非数字,等价于[^1-9] “\D”:表示匹配任意一个非数字 U、d、@、$、{ \w 匹配字母数字下划线,等价于[a-zA-Z_] “\w”:表示匹配一个字母或数字或下划线 a、b、e、a、6、1、 \W 匹配非字母数字下划线,等价于[^a-zA-Z] “\W”:表示匹配一个非字母或数字或下划线 !、#、@、%、(、*、/、-

[]字符匹配符的细节

  • 在[]中写的任何特殊符号,例如:.?*+=都相当于直接匹配对应的符号(可以理解为放进去就已经转义了)

选择匹配符

选择匹配符 作用 正则示例 匹配结果示例 | 表示可以匹配多个表达式、相当于或 “ab|bc|cd” : 表示可以匹配ab或者bc或者cd ab、bc、cd

限定符

限定符 作用 正则示例 匹配结果示例 ? 表示匹配0个或者1个 “\d[abc]?”:表示匹配一个数字开头、而后可以跟abc中的任意一个字母,也可以不跟 1a、3b、5c、1、5 + 表示匹配1个或多个 “\d[795]+”:表示匹配一个数字开头、而后至少由一个数字7、9、5任意组合的字符串 17、175、395、5957759 * 表示匹配0个或多个 “\w[1-9]*”:表示匹配一个字母或数字、下划线开头,而后跟0个或者人一个1~9之间的字符 z12、w98、s125468 {n} 其中的n代表数量、限定匹配多少个字符 “\d{3}”:匹配连续3个数字 159、512、202、894 {n,} 表示匹配的字符最少为n个,没有最多的限制 “\d{2,}”:匹配最少2个数字或者更多 10、14、6661、23421、2341234、124 {n,m} 表示匹配的字符最少为n个,最多为m个 “\d{2,4}”:匹配最少2个数字,最多4个数字 19、98、559、5598、1125、558

定位符

定位符 作用 正则示例 匹配结果示例 ^ 匹配字符串的开头 “^\d[a-z]{2}”:表示匹配一个数字开头(整个字符串),2个字母结尾 例如1ab13这个字符串能够呗匹配到,但是d1ab这个字符串匹配不到 $ 匹配字符串的结尾 “\d[a-z]{2}$”:表示匹配一个数字开头,2个字母结尾(字符串结尾) 例如1ab这个字符串能够呗匹配到,但是2abc这个字符串匹配不到 \b 匹配字符串的边界 “abc\b”:表示匹配字符串边界的abc,例如一个字符串”abc adsabc asdfabcd abcsw” 可以匹配到2个abc \B 匹配字符串的非边界(反过来) “abc\B”:表示匹配字符串非边界的abc,例如一个字符串”babc adsabc asdfabcd abcsw” 只能匹配到最后一个子串abcsw中的一个abc

分组组合和反向引用符(配合使用)

捕获分组、非捕获分组、反向引用

捕获分组

捕获分组构造形式 作用 正则示例 匹配结果示例 (pattern) 分组捕获 “(\d\d)(\d\d)”:匹配4个数字,分成了2组 可以group(1)和group(2)取出第一组和第二组的字符串 (?

非捕获分组

非捕获分组构造形式 作用 正则示例 匹配结果示例 (?:pattern) 匹配但不捕获该分组,也就是调用group()方法时无法取出该分组 “快乐(?: 水|果|花)”:不会将(?: pattern)中的表达式放入group()分组中 快乐水、快乐果、快乐花 (?=pattern) 非捕获匹配 “Windows(?=2022|2021)” 可以匹配到”Windwos2022″或”Windwos2021″中的”Windows” (?!pattern) 与上一个相反 “Windows(?=2022|2021)” 可以匹配到”Windwos2014″或”Windwos98″中的”Windows”,但就是匹配不到”Windwos2022″或”Windows2021″中的”Windwos”

反向引用(内部、外部)

我们先来看一个需求:需要匹配一串连续的4个数字,并且保证第一位数字与第四位数字相同,第二位数字与第三位数字相同。例如:1001、8448、4554

  • 反向引用的语法:
  • 在正则表达式内部使用时候只需要 ” \group“,这里的group表示引用 第几组
  • 在正则表达式外部时使用” $group“,例如matcher.replaceAll()方法4
  • 第几组是根据正则表达式中的捕获分组来决定的,第一个括号是第一组,以此类推
  • 具体的使用将会在应用实例中演示

应用实例

实现不区分大小写

如下正则表达式:

  • “abc” :表示匹配abc,区分大小写
  • “(?i)abc”: 表示匹配abc,不区分大小写
  • “ab(?i)c”: 表示匹配时,c不区分大小写
  • “a((?i)b)c”:表示匹配时,b不区分大小写

贪婪匹配、非贪婪匹配(懒惰匹配)

  • 如果想要实现非贪婪匹配,需要在限定符后添加一个”?”也就是问号。
  • 例如有一个字符串”aaa”,正则表达式为:”a+”,此时默认为贪婪匹配,因此只有一个结果:”aaa”
  • 例如有一个字符串”aaa”,正则表达式为:”a+?”,此时为非贪婪匹配,因此可以匹配到3个结果:”a”、”a”、”a”

常用元字符练习

获取汉字

public class RegExp02 {
    public static void main(String[] args) {
        String content = "&#x4ECA;&#x5929;  &#x4F60; &#x6CA1;&#x60F3;&#x5230; &#x5427;";

        // &#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;
        String regExp = "[\\u4e00-\\u9fa5]+";

        Pattern pattern = Pattern.compile(regExp);

        Matcher matcher = pattern.matcher(content);

        // &#x8BB0;&#x5F55;&#x627E;&#x5230;&#x4E86;&#x591A;&#x5C11;&#x7EC4;
        int count = 0;

        while (matcher.find()) {
            System.out.println("&#x627E;&#x5230;&#x4E86;&#xFF0C;&#x8FD9;&#x662F;&#x7B2C;" + ++count + "&#x7EC4;&#xFF1A;" + matcher.group(0));
        }
    }
}

获取邮政编码:要求是1-9开头的六位数

public class RegExp02 {
    public static void main(String[] args) {
        String content = "15812 595125 951236 015487 6514 25654 00154";

        // &#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;
        String regExp = "[1-9]\\d{5}";

        Pattern pattern = Pattern.compile(regExp);

        Matcher matcher = pattern.matcher(content);

        // &#x8BB0;&#x5F55;&#x627E;&#x5230;&#x4E86;&#x591A;&#x5C11;&#x7EC4;
        int count = 0;

        while (matcher.find()) {
            System.out.println("&#x627E;&#x5230;&#x4E86;&#xFF0C;&#x8FD9;&#x662F;&#x7B2C;" + ++count + "&#x7EC4;&#xFF1A;" + matcher.group(0));
        }
    }
}

QQ号码:要求1-9开头的一个(5位数-10位数)

public class RegExp02 {
    public static void main(String[] args) {
        String content = "2571986664aaf257198666dsf25719#$!02121/*-abcadsf";

        // &#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;
        String regExp = "[1-9]\\d{4,9}";

        Pattern pattern = Pattern.compile(regExp);

        Matcher matcher = pattern.matcher(content);

        // &#x8BB0;&#x5F55;&#x627E;&#x5230;&#x4E86;&#x591A;&#x5C11;&#x7EC4;
        int count = 0;

        while (matcher.find()) {
            System.out.println("&#x627E;&#x5230;&#x4E86;&#xFF0C;&#x8FD9;&#x662F;&#x7B2C;" + ++count + "&#x7EC4;&#xFF1A;" + matcher.group(0));
        }
    }
}

手机号码:以13、14、15、18开头的11位数

public class RegExp02 {
    public static void main(String[] args) {
        String content = "15277303777a2134a1427730377734098asdf1527730377adf";

        // &#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;
        String regExp = "1[3|4|5|8]\\d{9}";

        Pattern pattern = Pattern.compile(regExp);

        Matcher matcher = pattern.matcher(content);

        // &#x8BB0;&#x5F55;&#x627E;&#x5230;&#x4E86;&#x591A;&#x5C11;&#x7EC4;
        int count = 0;

        while (matcher.find()) {
            System.out.println("&#x627E;&#x5230;&#x4E86;&#xFF0C;&#x8FD9;&#x662F;&#x7B2C;" + ++count + "&#x7EC4;&#xFF1A;" + matcher.group(0));
        }
    }
}

URL:匹配一个URL网址,可以带端口及不带端口

public class RegExp02 {
    public static void main(String[] args) {
//        String content = "https://vip.iqiyi.com/cps_pc.html?a=b&b=c";
        String content = "https://vip.iqiyi.com:3918/cps_pc.html?a=b&b=c";

        // &#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;
        String regExp = "^(http|https)://([\\w+.]+)(:\\d+)?/[\\w.]+\\??[\\S]*$";

        Pattern pattern = Pattern.compile(regExp);

        Matcher matcher = pattern.matcher(content);

        while (matcher.find()) {
            System.out.println("&#x627E;&#x5230;&#x4E86;&#xFF1A;" + matcher.group(0));
        }
    }
}

按照如下电子邮件规则编写正则表达式

  1. 只能有一个@
  2. @前面是用户名,可以是a-z A-Z 0-9 _ – 等字符
  3. @后面是域名,域名只能是英文字母,比如sohu.com或baidu.org.cn
public class RegExp02 {
    public static void main(String[] args) {
        String content = "codeStars@163.com.cn";

        // &#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;
        String regExp = "^[\\w-]+@[a-zA-Z0-9.]*[a-zA-Z0-9]+$";

        if (content.matches(regExp)) {
            System.out.println("&#x5339;&#x914D;&#x6210;&#x529F;");
        }else {
            System.out.println("&#x5339;&#x914D;&#x5931;&#x8D25;");
        }
    }
}

要求匹配到整数或者小数,要求考虑正数及负数

public class RegExp02 {
    public static void main(String[] args) {
        // &#x9700;&#x8981;&#x9650;&#x5236;00.45&#x3001;-00.45&#x4E4B;&#x7C7B;&#x7684;&#x9519;&#x8BEF;&#x8F93;&#x5165;&#x683C;&#x5F0F;
        // 123 -345 34.89 -87.9 -0.01 0.45 -00.45
        String content = "-0.01";

        // &#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;
        String regExp = "^[+-]?([\\d+|0?])\\.?\\d+$";

        Pattern pattern = Pattern.compile(regExp);

        Matcher matcher = pattern.matcher(content);

        while (matcher.find()) {
            System.out.println("&#x627E;&#x5230;&#xFF1A;" + matcher.group(0));
        }
    }
}

对一个url进行解析

  1. 获取到协议: http或https
  2. 域名是什么?
  3. 端口是什么?
  4. 文件名是什么?
public class RegExp02 {
    public static void main(String[] args) {
        String content = "https://mail.163.com:8080/register/success.htm";

        // &#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#x601D;&#x8DEF;
        // 1. &#x5148;&#x83B7;&#x53D6;&#x5230;&#x534F;&#x8BAE;(http|https)&#xFF0C;&#x4EE5;&#x53CA;&#x589E;&#x52A0;&#x56FA;&#x5B9A;&#x7684;&#x5206;&#x9694;&#x7B26; ://
        // 2. &#x83B7;&#x53D6;&#x57DF;&#x540D;([\\w.]+)
        // 3. &#x83B7;&#x53D6;&#x7AEF;&#x53E3;([:\\d]+)
        // 4. &#x8FC7;&#x6EE4;&#x4E0D;&#x9700;&#x8981;&#x6355;&#x83B7;&#x7684;&#x5185;&#x5BB9;(?:[\\w]+/)+
        // 5. &#x83B7;&#x53D6;&#x6587;&#x4EF6;&#x540D; ([\\w.]+)
        String regExp = "(http|https)://([\\w.]+)([:\\d]+)(?:[\\w]+/)+([\\w.]+)";

        Pattern pattern = Pattern.compile(regExp);

        Matcher matcher = pattern.matcher(content);

        while (matcher.find()) {
            System.out.println("&#x534F;&#x8BAE;&#x4E3A;&#xFF1A;" + matcher.group(1));
            System.out.println("&#x57DF;&#x540D;&#x4E3A;&#xFF1A;" + matcher.group(2));
            System.out.println("&#x7AEF;&#x53E3;&#x4E3A;&#xFF1A;" + matcher.group(3));
            System.out.println("&#x8D44;&#x6E90;&#x540D;&#x79F0;&#x4E3A;&#xFF1A;" + matcher.group(4));
        }
    }
}

非捕获分组练习

获取Windows10和Windows11中的Windows,不包括Windows12、Windows2018中的Windows

public class RegExp02 {
    public static void main(String[] args) {
        String content = "Windows2211 Windows10 Windows11 Windows12 Windows2018";

        // &#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;  &#x83B7;&#x53D6;Windows10&#x548C;Windows11&#x4E2D;&#x7684;Windows&#xFF0C;&#x4E0D;&#x5305;&#x62EC;Windows12&#x3001;Windows2018&#x4E2D;&#x7684;Windows
        String regExp = "Windows(?=10|11)";

        Pattern pattern = Pattern.compile(regExp);

        Matcher matcher = pattern.matcher(content);

        while (matcher.find()) {
            System.out.println("&#x627E;&#x5230;&#xFF1A;" + matcher.group(0));
            System.out.println("&#x7D22;&#x5F15;&#x5F00;&#x59CB;&#x4F4D;&#x7F6E;&#x4E3A;&#xFF1A;" + matcher.start());
            System.out.println("&#x7D22;&#x5F15;&#x7ED3;&#x675F;&#x4F4D;&#x7F6E;&#x4E3A;&#xFF1A;" + (matcher.end() - 1));
        }
    }
}

JAVA入门基础_从零开始的培训_JAVA中的正则表达式、处理文本的利器(五)

获取不包括Windows10和Windows11中的Windows,其他的都要,例如Windows12、Windows2018中的Windows

public class RegExp02 {
    public static void main(String[] args) {
        String content = "Windows2211 Windows10 Windows11 Windows12 Windows2018";

        // &#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;  &#x83B7;&#x53D6;&#x4E0D;&#x5305;&#x62EC;Windows10&#x548C;Windows11&#x4E2D;&#x7684;Windows&#xFF0C;&#x5176;&#x4ED6;&#x7684;&#x90FD;&#x8981;&#xFF0C;&#x4F8B;&#x5982;Windows12&#x3001;Windows2018&#x4E2D;&#x7684;Windows
        String regExp = "Windows(?!10|11)";

        Pattern pattern = Pattern.compile(regExp);

        Matcher matcher = pattern.matcher(content);

        while (matcher.find()) {
            System.out.println("&#x627E;&#x5230;&#xFF1A;" + matcher.group(0));
            System.out.println("&#x7D22;&#x5F15;&#x5F00;&#x59CB;&#x4F4D;&#x7F6E;&#x4E3A;&#xFF1A;" + matcher.start());
            System.out.println("&#x7D22;&#x5F15;&#x7ED3;&#x675F;&#x4F4D;&#x7F6E;&#x4E3A;&#xFF1A;" + (matcher.end() - 1));
        }
    }
}

JAVA入门基础_从零开始的培训_JAVA中的正则表达式、处理文本的利器(五)

反向引用练习(注意与捕获分组使用)

实现匹配1221、2332、4554之类的数字

public class RegExp02 {
    public static void main(String[] args) {
        String content = "4554 2662 1234 8448 9119 1331 5897 2222";

        // &#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;
        String regExp = "(\\d)(\\d)\\2\\1";

        Pattern pattern = Pattern.compile(regExp);

        Matcher matcher = pattern.matcher(content);

        while (matcher.find()) {
            System.out.println("&#x627E;&#x5230;&#xFF1A;" + matcher.group(0));
        }
    }
}

要求满足前面是一个五位数,加一个-号,后续是一个九位数,每3位要相同

例如:13541-555222111、59511-666333444

public class RegExp02 {
    public static void main(String[] args) {
        String content = "13541-555222111&#x3001;59511-666333444&#x3001;12465-123456789";

        // &#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;
        String regExp = "\\d{5}-(\\d)\\1{2}(\\d)\\2{2}(\\d)\\3{2}";

        Pattern pattern = Pattern.compile(regExp);

        Matcher matcher = pattern.matcher(content);

        while (matcher.find()) {
            System.out.println("&#x627E;&#x5230;&#xFF1A;" + matcher.group(0));
        }
    }
}

解决结巴语句,例如:今今…,,天也是…个好..好好好….日日子转换为 今天是个好日子

public class RegExp02 {
    public static void main(String[] args) {
        String content = "&#x4ECA;&#x4ECA;...,,&#x5929;&#x4E5F;&#x662F;...&#x4E2A;&#x597D;..&#x597D;&#x597D;&#x597D;....&#x65E5;&#x65E5;&#x5B50;";

        // &#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;
        // &#x601D;&#x8DEF;
        // 1. &#x5148;&#x5C06;&#x6240;&#x6709;&#x5176;&#x4ED6;&#x7684;&#x7279;&#x6B8A;&#x7B26;&#x53F7;&#x53BB;&#x9664;&#x6389;&#xFF0C;&#x7531;&#x4E8E;&#x8BE5;&#x5B57;&#x7B26;&#x4E32;&#x4E2D;&#x53EA;&#x6709;. &#x548C; , &#x6240;&#x4EE5;&#x53EA;&#x653E;&#x4E86;2&#x4E2A;
        String regExp = "[.,\\s]+";

        Pattern pattern = Pattern.compile(regExp);
        Matcher matcher = pattern.matcher(content);

        // 1.1 &#x5C06;&#x627E;&#x5230;&#x7684;&#x7279;&#x6B8A;&#x7B26;&#x53F7;&#x90FD;&#x66FF;&#x6362;&#x6210;&#x7A7A;&#x5B57;&#x7B26;&#x4E32;&#xFF0C;&#x8BE5;&#x884C;&#x6267;&#x884C;&#x540E;content&#x5C31;&#x53D8;&#x6210;&#x4E86;&#xFF1A;&#x4ECA;&#x4ECA;&#x5929;&#x4E5F;&#x662F;&#x4E2A;&#x597D;&#x597D;&#x597D;&#x597D;&#x65E5;&#x65E5;&#x5B50;
        content = matcher.replaceAll("");
        // &#x7F16;&#x5199;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#xFF0C;&#x5339;&#x914D;&#x4E00;&#x4E2A;&#x975E;&#x7A7A;&#x5B57;&#x7B26;&#x800C;&#x540E;&#x5FC5;&#x987B;&#x6709;1&#x4E2A;&#x6216;&#x591A;&#x4E2A;&#x4E0E;&#x5176;&#x4E00;&#x6837;&#x7684;&#x5B57;&#x7B26;
        regExp = "(\\S)\\1+";

        // 2. &#x91CD;&#x65B0;&#x521B;&#x5EFA;Pattern&#x548C;Matcher
        pattern = Pattern.compile(regExp);
        matcher = pattern.matcher(content);

        // 3. &#x4F7F;&#x7528;replaceAll&#x65B9;&#x6CD5;&#x6765;&#x66FF;&#x6362;&#x6389;&#xFF0C;&#x9700;&#x8981;&#x4F7F;&#x7528;&#x5230;&#x5916;&#x90E8;&#x5F15;&#x7528;$
        //  &#x4E0A;&#x9762;&#x7F16;&#x5199;&#x7684;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#x4F1A;&#x627E;&#x5230;3&#x4E2A;&#x5B57;&#x7B26;&#x4E32;&#xFF0C;&#x5206;&#x522B;&#x4E3A;&#xFF1A;&#x4ECA;&#x4ECA;&#x3001;&#x597D;&#x597D;&#x597D;&#x597D;&#x3001;&#x65E5;&#x65E5;
        // &#x5E95;&#x5C42;&#x4F1A;&#x5FAA;&#x73AF;&#x7684;&#x8C03;&#x7528;find()&#x65B9;&#x6CD5;&#xFF0C;&#x76F8;&#x5F53;&#x4E8E;&#x627E;&#x5230;&#x4E00;&#x4E2A;&#x5B57;&#x7B26;&#x4E32;&#xFF0C;&#x5C31;&#x7528;&#x5176;&#x7B2C;&#x4E00;&#x7EC4;&#x7684;&#x5185;&#x5BB9;&#x66FF;&#x6362;&#x6574;&#x4E2A;&#x5B57;&#x7B26;&#x4E32;&#xFF0C;&#x4EE5;&#x6B64;&#x7C7B;&#x63A8;&#x5C31;&#x80FD;&#x5168;&#x90E8;&#x66FF;&#x6362;
        String newContent = matcher.replaceAll("$1");
        System.out.println(newContent); // &#x8F93;&#x51FA;&#x7ED3;&#x679C;&#xFF1A;&#x4ECA;&#x5929;&#x4E5F;&#x662F;&#x4E2A;&#x597D;&#x65E5;&#x5B50;
    }
}

Original: https://www.cnblogs.com/itdqx/p/16540714.html
Author: code_Stars
Title: JAVA入门基础_从零开始的培训_JAVA中的正则表达式、处理文本的利器(五)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/594032/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 配置 JAVA 环境 JDK + IDEA

    搜索 ORACLE 官网,找到 JDK,下载 JDK8 版本 / JDK11 版本 选择合适的路径,我这里放在了 D 盘 配置下方系统环境变量,变量名为 JAVA_HOME,把刚刚…

    Java 2023年6月5日
    085
  • Java核心技术-泛型、集合

    Day10 泛型程序设计 对于Java泛型的转换需要记住一下几个事实: 虚拟机中没有泛型,只有普通的类和方法 所有的类型参数都会替换为他们的限定类型 会合成桥方法来保持多态 为保持…

    Java 2023年6月5日
    0100
  • SpringCloud中使用Nacos作为配置中心原理

    使用了是Nacos的自动配置依赖 com.alibaba.cloud spring-cloud-starter-alibaba-nacos-config 2.2.5.RELEASE…

    Java 2023年5月30日
    094
  • Android性能优化之利用Rxlifecycle解决RxJava内存泄漏

    前言: 其实RxJava引起的内存泄漏是我无意中发现了,本来是想了解Retrofit与RxJava相结合中是如何通过适配器模式解决的,结果却发现了RxJava是会引起内存泄漏的,所…

    Java 2023年5月29日
    0120
  • Linux测试端口的连通性

    在日常开发过程中,有时会遇到需要测试测试某些端口是否可以连通的问题,常用的方法有以下 1、telnet ip port ip是指测试主机的ip port是指测试主机的端口 [roo…

    Java 2023年6月8日
    0100
  • Java动态脚本Groovy,高级啊!

    前言:请各大网友尊重本人原创知识分享,谨记本人博客: 南国以南i 简介: Groovy是用于Java虚拟机的一种敏捷的动态语言,它是一种成熟的面向对象编程语言,既可以用于面向对象编…

    Java 2023年6月5日
    0117
  • SpringBoot接口-如何优雅的对参数进行校验?

    在以SpringBoot开发Restful接口时, 对于接口的查询参数后台也是要进行校验的,同时还需要给出校验的返回信息放到上文我们统一封装的结构中。那么如何优雅的进行参数的统一校…

    Java 2023年6月6日
    0112
  • 基础常用API总结2

    java.lang包下 返回值类型 方法 功能 boolean matches(String regex) 如果 当前字符串中regex(正则表达式)所表示的字符,如果有返回tur…

    Java 2023年6月8日
    0112
  • Netty内存池的整体架构

    一、为什么要实现内存管理? Netty 作为底层网络通信框架,网络IO读写必定是非常频繁的操作,考虑到更高效的网络传输性能,堆外内存DirectByteBuffer必然是最合适的选…

    Java 2023年6月15日
    094
  • Mybatis系列全解(五):全网最全!详解Mybatis的Mapper映射文件

    封面:洛小汐作者:潘潘 若不是生活所迫,谁愿意背负一身才华。 ; 前言 上节我们介绍了 《 Mybatis系列全解(四):全网最全!Mybatis配置文件 XML 全貌详解 》,内…

    Java 2023年6月13日
    0103
  • JetBrains IDE全新UI预览版来了,要做简洁与强大兼顾的IDE

    5月23日,JetBrains发布了一篇博文,透露他们正在实现一套全新的界面界面。 他们认为目前行业中的用户界面趋势已经发生了演变,很多新用户认为JetBrains IDE的界面过…

    Java 2023年6月9日
    093
  • MySQL九:MVCC能否解决幻读问题

    转载~ 幻读【前后多次读取,数据总量不一致】 同一个事务里面连续执行两次同样的sql语句,可能导致不同结果的问题,第二次sql语句可能会返回之前不存在的行。 事务A执行多次读取操作…

    Java 2023年6月8日
    0106
  • SpringCloudAlibaba分布式事务解决方案Seata实战与源码分析-上

    概述 定义 Spring Cloud Alibaba Seata 官网地址 https://seata.io/zh-cn/ 最新版本 1.5.2Spring Cloud Aliba…

    Java 2023年6月5日
    092
  • [springmvc]mvc的多种方式实现请求转发与重定向

    3.restful风格 RESTFUL是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用XML格式定义或JSON格式定义。 RESTFUL适用于移动互联网厂商作为业务接…

    Java 2023年6月6日
    0109
  • Mysql学习

    显示字符集编码 mysql架构 逻辑架构 Client : 提供连接MySQL服务器功能的常用工具集 Server : MySQL实例,真正提供数据存储和数据处理功能的MySQL服…

    Java 2023年6月8日
    099
  • 从零开始实现一个分布式RPC框架

    该rpc框架是一个mini版的dubbo。学习rpc之前,建议先了解NIO,Netty和Dubbo等知识。请移步网络编程 前言:(借用阿里大佬的一段话) 为什么要自己写一个RPC框…

    Java 2023年6月7日
    0109
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球