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)

大家都在看

  • Controller以及RestFul风格

    Controller以及RestFul风格 控制器Controller 控制器复杂提供访问应用程序的行为,通常通过接口定义或注解定义两种方式实现 控制器负责解析用户的请求并将其转换…

    Java 2023年6月13日
    0118
  • 热部署只知道devtools吗?JRebel不香吗?

    前言 JRebel收费怎么破? 什么是本地热部署? 什么是远程热部署? JRebel和devtools的区别 如何安装JRebel? 如何本地热部署? 如何远程热部署? 多模块开发…

    Java 2023年6月14日
    0106
  • 【手把手】光说不练假把式,这篇全链路压测实践探索

    Hello,大家好呀,前两篇文章,我们说了下关于全链路压测的意义、整体架构,以及5种压测的方案。 前面两篇基本都属于比较理论的内容,今天这篇咱们来点实践的东西,手把手带你搞出一个压…

    Java 2023年6月15日
    0105
  • Spring IOC源码研究笔记(2)——ApplicationContext系列

    1.1. 继承关系 非web环境下,一般来说常用的就两类ApplicationContext: 配置形式为XML的:ClassPathXmlApplicationContext、F…

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

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

    Java 2023年6月9日
    086
  • idea快捷键

    常用快捷键 https://mp.weixin.qq.com/s/-rB1AdCRUkryhKcdb96heg Original: https://www.cnblogs.com/…

    Java 2023年6月7日
    083
  • github学生认证——申请学生开发包

    写在前面 申请学生认证的好处: GitHub学生的免费AWS Educate入门帐户,价值100美元。 专业的桌面IDE:IntelliJ IDEA,PyCharm等。学生的免费订…

    Java 2023年6月9日
    0101
  • String,StringBuilder和StringBuffer的特点和使用场景

    这三个类是平时开发中经常遇到的,主要差别是运行速度和线程安全,使用起来String最方便了,另外两个稍微复杂一些。 从运行速度角度看,StringBuilder>String…

    Java 2023年6月6日
    073
  • AOP

    AOP AOP的入门案例: AOP的工作流程 SpringAop的本质是:代理模式 AOP的切入点表达式 重用切入点表达式: ①声明 @Pointcut(“execut…

    Java 2023年6月16日
    061
  • SpringBoot扩展接口- Bean实例化前后扩展点

    常用的扩展接口: 1、ApplicationContextAware:获取应用上下文 2、BeanPostProcessor 接口在对象实例化后, 初始化方法调用前后做前置处理和后…

    Java 2023年5月30日
    090
  • 一个注解@Recover搞定丑陋的循环重试代码

    使用背景 在实际项目中其中一部分逻辑可能会因为调用了外部服务或者等待锁等情况下出现不可预料的异常,在这个时候我们可能需要对调用这部分逻辑进行重试,代码里面主要就是使用for循环写一…

    Java 2023年6月5日
    082
  • Java——字节码技术

    字节码 1.1 什么是字节码? Java之所以可以”一次编译,到处运行”,一是因为JVM针对各种操作系统、平台都进行了定制,二是因为无论在什么平台,都可以编…

    Java 2023年5月29日
    0106
  • Java-Stream流方法学习及总结

    1 前言 Stream是一个来自数据源的元素队列并支持聚合操作,其中具有以下特性: Stream只负责计算,不存储任何元素,元素是特定类型的对象,形成一个队列 数据源可以实集合、数…

    Java 2023年6月8日
    077
  • K均值算法

    一、概念 K-means中心思想:事先确定常数K,常数K意味着最终的聚类类别数,首先随机选定初始点为质心,并通过计算每一个样本与质心之间的相似度(这里为欧式距离),将样本点归到最相…

    Java 2023年6月7日
    0130
  • Java开发笔记(一百四十三)FXML布局的基本格式

    前面介绍了JavaFX的常见控件用法,虽然JavaFX控件比起AWT与Swing要好用些,但是一样通过代码编写控件界面,并没有提高什么开发效率。要想浏览界面的展示效果,都必须运行测…

    Java 2023年6月6日
    080
  • 大头儿子和小头爸爸的战斗–java字符和字符串

    故事背景 一座普普通通的小屋里,住着大头儿子、小头爸爸和围裙妈妈。在他们普普通通的生活中,总是响起充满欢乐的笑声。最温暖的家又成了他们每个人的爱的源泉。 《大头儿子和小头爸爸》是孩…

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