正则表达式

什么是正则表达式?

正则表达式是一种用于匹配和操作文本的强大工具。它由一系列字符和特殊字符组成的模式,用于描述要匹配的文本模式。正则表达式可以在文本中查找、替换、提取和验证特定的模式。在处理大量文本数据时,正则表达式提供了极大的便利。

例如,我们要将下面这一段文字中《》中的文字全部提取出来。

复制代码
周星驰(Stephen Chow),1962年6月22日出生于中国香港,祖籍浙江宁波,华语影视男演员、导演、编剧、监制、制片人、出品人、主持人、国家一级演员、西南民族大学客座教授、中国人民大学教授;1980年成为丽的电视台特约演员,从而进入演艺圈,1981年出演荧幕处女作《IQ成熟时》,1988年将演艺事业重心转向大银幕,在电影《霹雳先锋》中首次担任男主角,1990年凭借喜剧片《一本漫画闯天涯》确立其无厘头表演风格,之后又凭借喜剧动作片《赌圣》、喜剧片《逃学威龙》两度打破香港电影票房纪录,1993年上映的古装喜剧片《唐伯虎点秋香》使得周星驰第四次拿到香港电影年度票房冠军,1994年开始转型,首度出任导演的电影作品是《国产凌凌漆》,1995年主演的喜剧爱情片《大话西游》成为其后现代电影代表作,2001年自导自演的喜剧片《少林足球》打破香港电影票房纪录,2003年成为美国《时代周刊》封面人物,2013年执导古装电影《西游·降魔篇》,该片以2.18亿美元票房成绩打破华语电影全球票房纪录,2016年担任科幻喜剧片《美人鱼》的导演、编剧、制片人,该片创下中国内地影史单片票房纪录;作为演员,他获得过第21届香港电影金像奖最佳男主角奖、亚太电影节最佳男主角奖等奖项,入选“中国电影百年百位优秀演员”以及“中国电影百年名人堂”;作为导演,他先后获得第21届香港电影金像奖最佳导演奖、第42届台湾电影金马奖最佳导演等奖项。

如果使用传统的遍历方式,代码量大,效率不高。

正则表达式:

import java.util.regex.Matcher;
import java.util.regex.Pattern;
​
public class Regexp_1 {
    public static void main(String[] args) {
        String text = "周星驰(Stephen Chow),1962年6月22日出生于中国香港,祖籍浙江宁波 [178]," +
                "华语影视男演员、导演、编剧、监制、制片人、出品人、主持人、国家一级演员、西南民族大学客座教授 [82]、中国人民大学教授 [82]。\n" +
                "1980年,成为丽的电视台特约演员,从而进入演艺圈 [32]。1981年,出演荧幕处女作《IQ成熟时》 " +
                "[161]。1988年,将演艺事业的重心转向大银幕,在电影《霹雳先锋》中首次担任男主角 " +
                "[91]。1990年,凭借喜剧片《一本漫画闯天涯》确立其无厘头的表演风格 [137]," +
                "之后又凭借喜剧动作片《赌圣》、喜剧片《逃学威龙》两度打破香港电影票房纪录 [1] [142]。1" +
                "993年上映的古装喜剧片《唐伯虎点秋香》使得周星驰第四次拿到香港电影年度票房冠军 [136]。1994年,周星驰开始转型," +
                "他首度出任导演的电影作品是《国产凌凌漆》 [94]。1995年,主演的喜剧爱情片《大话西游》成为周星驰后现代电影的代表作 [92]。" +
                "2001年,自导自演的喜剧片《少林足球》打破香港电影票房纪录 [24]。2003年,成为美国《时代周刊》封面人物 [4]。" +
                "2013年,执导古装电影《西游·降魔篇》,该片以2.18亿美元的票房成绩打破华语电影在全球的票房纪录 [5]。" +
                "2016年,担任科幻喜剧片《美人鱼》的导演、编剧、制片人 [6-7],该片创下中国内地影史单片票房纪录 [81] [84]。\n" +
                "作为演员,他获得过第21届香港电影金像奖最佳男主角奖,亚太电影节最佳男主角奖等奖项 [3] [139]," +
                "入选"中国电影百年百位优秀演员"以及"中国电影百年名人堂" [85] [138]。作为导演,他先后获得第21届香港电影金像奖最佳导演奖、" +
                "第42届台湾电影金马奖最佳导演等奖项 [3] [80]。";
​
        String content = "127.0.0.1, 192.168.31.5, 128.165.22.43";
        //1. 先创建一个pattern对象,模式对象,可以理解成一个正则表达式对象
        Pattern pattern = Pattern.compile("《(.*?)》");
        //2. 创建一个匹配器对象
        //理解: 就是match匹配器按照pattern模式,到content文本去匹配
        //找到就返回true,否则就返回flase
        Matcher matcher = pattern.matcher(text);
        //3. 开始循环匹配
        while (matcher.find()) {
            //匹配内容,文本,放到mgroup(0)中
            System.out.println("找到 "+matcher.group(0));
        }
    }
}
复制代码

运行结果:

基本语法

转义字符

  1. \. - 匹配字面意义上的句点(.),而不是"任意单个字符"的通配符。

  2. \\ - 匹配反斜杠(\)本身。

  3. \* - 匹配星号(*),而不是"零次或多次"的重复符号。

  4. \+ - 匹配加号(+),而不是"一次或多次"的重复符号。

  5. \? - 匹配问号(?),而不是"零次或一次"的限定符。

  6. \| - 匹配竖线(|),而不是"或"操作符。

  7. \(\) - 匹配圆括号(()),而不是用于分组的符号。

  8. \{\} - 匹配花括号({}),而不是用于指定重复次数的符号。

  9. \[\] - 匹配方括号([]),而不是用于定义字符集的符号。

  10. \^ - 匹配脱字符(^),而不是"行的开始"的定位符。

  11. \$ - 匹配美元符号($),而不是"行的结束"的定位符。

  12. \- - 在字符集中匹配连字符(-),而不是用于指定范围的符号。

在Java字符串中,反斜杠(\)是一个转义字符,用于引入特殊字符序列。例如,\n 表示新行,\t 表示制表符等。因此,如果你想在字符串中表示一个实际的反斜杠字符,你需要使用双反斜杠(\\)来转义它。

示例:

java 复制代码
public static void main(String[] args) {
        String content = "asd(qeq(adada((";
        String RegStr = "\\(";
        Pattern pattern = Pattern.compile(RegStr);
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            System.out.println("找到 "+matcher.group());
        }
    }

字符匹配符

java 复制代码
public static void main(String[] args) {
        String content = "ada13A a@";
//        String regStr = "[a-z]";//匹配a-z之间任意一个字符
//        String regStr = "[A-Z]";//匹配A-Z之间任意一个字符
​
//        String regStr = "[0-9]";//匹配0-9之间任意一个字符
​
//        String regStr = "abc";//匹配abc字符,字符串默认区分大小写
//        String regStr = "(?i)abc";//匹配abc字符,不区分大小写
//        String regStr = "a(?i)bc";//匹配abc字符,bc不区分大小写
//        String regStr = "a((?i)b)c";//匹配abc字符,b不区分大小写
​
//        String regStr = "[^0-9]";//匹配任何非数字字符。
//        String regStr = "//D";//匹配非数字
//        String regStr = "//d";//匹配数字
//        String regStr = "//w";//匹配字母,数字,下划线
//        String regStr = "//W";//匹配非w
//        String regStr = "//s";//匹配任何空白字符(小写s)
//        String regStr = "//S";//匹配任何非空白字符(大写S)
//        String regStr = ".";//匹配除了\n之外所有字符 要是想用 . 只能转义 \\.
//        String regStr = "ad{1}";//匹配ad
​
        //说明
        //1. 当出现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));
        }
​
    }

修饰符

修饰符 含义 描述
i ignore - 不区分大小写 将匹配设置为不区分大小写,搜索时不区分大小写: A 和 a 没有区别。
g global - 全局匹配 查找所有的匹配项。
m multi line - 多行匹配 使边界字符 ^$ 匹配每一行的开头和结尾,记住是多行,而不是整个字符串的开头和结尾。
s 特殊字符圆点 . 中包含换行符 \n 默认情况下的圆点 . 是匹配除换行符 \n 之外的任何字符,加上 s 修饰符之后, . 中包含换行符 \n。

选择匹配符

选择匹配符 是正则表达式中的一个元字符,用于在多个模式之间进行"或"匹配。它的符号是 |,表示"匹配左边或右边的表达式"。

java 复制代码
public static void main(String[] args) {
        String content = "韩 han 汗流浃背";
        String regStr = "han|韩|汗";

        Pattern pattern = Pattern.compile(regStr, Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            System.out.println("找到 " + matcher.group(0));
        }
    }

限定符

限定符用于指定字符或分组的重复次数。

常见得分限定符
常见限定符 描述
* 匹配前面的元素零次或多次。
+ 匹配前面的元素一次或多次。
? 匹配前面的元素零次或一次。
{n} 匹配前面的元素恰好 n 次。
{n,} 匹配前面的元素至少 n 次。
{n,m} 匹配前面的元素至少 n 次,至多 m 次。
复制代码
        
java 复制代码
String content = "31131aaad13";
//        String regStr = "a{3}";  aaa
//        String regStr = "1{2}";  11
//        String regStr = "\\d{2}";  匹配任意两位数字
​
​
        /**
         * {n,m}
         * 细节: java匹配默认是贪婪匹配,尽可能匹配多的
         * \\d{2,4}
         * 找到 3113
         * 找到 13
         */
//        String regStr = "\\d{2,4}";
​
        //+
//        String regStr = "1+";//匹配一个或者多个1
​
        //*
//        String regStr = "1+";//匹配0个1或者多个1
​
        //?
        String regStr = "d1?";//匹配d或者d1
​
        Pattern pattern = Pattern.compile(regStr, Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            System.out.println("找到 " + matcher.group(0));
        }
    }
贪婪匹配和非贪婪匹配

什么是贪婪匹配:默认情况下,量词(如 *+?{})是贪婪匹配 的,即它们会尽可能多地匹配字符。如果你想取消贪婪匹配,改为非贪婪匹配 (也称为懒惰匹配 ),可以在量词后面加上 ?

贪婪匹配

java 复制代码
String text = "aabab";
String regex = "a.*b"; // 贪婪匹配
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
​
while (matcher.find()) {
    System.out.println("找到匹配: " + matcher.group());
}
输出

找到匹配: aabab

非贪婪匹配

java 复制代码
String text = "aabab";
String regex = "a*?b"; // 非贪婪匹配
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
​
while (matcher.find()) {
    System.out.println("找到匹配: " + matcher.group());
}
该案例目的是匹配a{}b
输出:

找到匹配: aab
找到匹配: ab

定位符

java 复制代码
public static void main(String[] args) {
        String content = "31131Saad";
        String content = "lllzkdjkkwlgs kkwl yxgs";
        //^ 指定起始字符
        //至少以一个数字开头,后接任意字母
//        String regStr = "^[0-9]+[a-z]*"; 输出 31131Saad
​
        //$ 指定结束字符
         //以任意数字开始,以任意字母结束
//        String regStr = "^[0-9]+[a-z]*$"; 输出31131Saad
​
        // \\b匹配目标字符串的边界 所谓的边界是指 字符串的 最后 ,或者被空格隔开的 子字符串的后面
//        String regStr = "kk\\b"; 输出为空
​
​
        // \B匹配目标字符串的非边界
        String regStr = "kk\\B"; //输出 找到 kk 找到 kk
​
​
        Pattern pattern = Pattern.compile(regStr, Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            System.out.println("找到 " + matcher.group(0));
        }
​
    }

分组

在正则表达式中,捕获分组 是一种将匹配的子字符串捕获并存储起来的机制。通过使用圆括号 (),可以将正则表达式的一部分标记为一个分组,匹配的内容会被捕获并可以在后续操作中使用。

捕获分组的作用

  1. 提取匹配的子字符串:可以从匹配的文本中提取特定的部分。

  2. 引用分组:可以在正则表达式中或替换操作中引用捕获的分组。

  3. 分组操作 :可以对分组进行量词操作(如 *+{})。

捕获分组的语法

非分组捕获

如果不需要捕获分组,可以使用非捕获分组语法 (?:...)。非捕获分组不会存储匹配的内容,也不会分配分组编号。

java 复制代码
public static void main(String[] args) {
        String content = "lll你好 lllHello lll同学";
        //找到你好lll Hellolll lll同学 的字符串
        //上面的写法可以等价非捕获分组
        String regStr = "lll(?:你好|Hello|同学)";
     输出: 找到 lll你好
          找到 lllHello
          找到 lll同学
         在这个例子中"(?:你好|Hello|同学)"匹配到了(你好|Hello|同学)但是并没有捕获,因此matcher.group(0) 返回整个匹配的字符串。
        
         
    String text = "2023-10-05";
    String regex = "(\\d{4})-(?:\\d{2})-(\\d{2})"; // 非捕获月份
    Pattern pattern = Pattern.compile(regex);
    Matcher matcher = pattern.matcher(text);
​
    if (matcher.find()) {
        System.out.println("年: " + matcher.group(1)); // 第1个分组
        System.out.println("日: " + matcher.group(2)); // 第2个分组
    }
     在这个例子中,(?:\\d{2}) 匹配了月份,但没有捕获它,因此 matcher.group(2) 直接对应日期的分组。
​
        //找到 lll 这个关键字,但是要求只是查找你好和Hello中的lll
//        String regStr = "lll(?=你好|Hello)";
         输出:找到 lll
              找到 lll
         (?=你好|Hello):这是一个正向零宽断言,表示 lll 后面必须紧跟 你好 或 Hello,但 你好 或 Hello 不会被包含在匹配结果中。
​
        //找到 lll 这个关键字,但是要求只是查找不是 lll你好 lllHello 中的lll
//        String regStr = "lll(?!你好|Hello)";
         输出:找到 lll
         (?!你好|Hello):这是一个负向零宽断言,表示 lll 后面不能是 你好 或 Hello。
         
        Pattern pattern = Pattern.compile(regStr);
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            System.out.println("找到 " + matcher.group(0));
        }
    }

匹配URL

java 复制代码
public static void main(String[] args) {
        String s = "https://www.bilibili.com/video/BV1Eq4y1E79W?spm_id_from=333.788.player.switch&vd_source=ab5366d1a2923f7defae5751c26f3023&p=18";
//        String s = "https://www.bilibili.com";
        Pattern pattern = Pattern.compile("^((https|http)://)?([\\w-]+\\.)+([\\w-])+(/[\\w-?~_+&=!^$.#]*)*$");
        Matcher matcher = pattern.matcher(s);
        if (matcher.find()) {
            System.out.println("满足格式");
        } else {
            System.out.println("不满足格式");
        }
    }

分析

^((https|http)://)?:可选的http://https://协议部分。? 是一个量词 ,表示前面的元素可以出现 0 次或 1 次

([\\w-]+\\.)+:匹配域名的子域名部分 www.bilibili. 因为有限定符+ 所以可以有多个 xxxx.

([\\w-])+:匹配顶级域名 com

(/[\\w-?~_+&=!^$.#]*)*:匹配路径及其查询参数部分,路径是可选的

matches

特性 matchesString 类) Matcher
功能 检查整个字符串是否完全匹配正则表达式 对字符串进行复杂的正则表达式匹配操作
返回值 boolean 无固定返回值,支持多种操作(如 findgroupreplaceAll 等)
匹配范围 必须从字符串的开头匹配到结尾 可以查找字符串中任意部分匹配的子字符串
使用场景 验证字符串是否符合特定格式 提取、替换、查找字符串中的特定模式

mathes: 整体匹配, 只返回tue或false ,当没有^时, matche 没有约束,就会错误 但是matches不会

java 复制代码
String text = "abc123";
String regex = "abc\\d+";
​
boolean result = text.matches(regex);
System.out.println(result); // 输出: true
java 复制代码
String text = "abc123 def456";
String regex = "\\d+";
​
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
​
while (matcher.find()) {
    System.out.println("找到匹配: " + matcher.group());
}
输出
找到匹配: 123
找到匹配: 456

Matcher 类常用方法

start & end

作用

  • start():返回当前匹配的子字符串的起始索引。

  • end():返回当前匹配的子字符串的结束索引。

java 复制代码
public static void main(String[] args) {
        String s = "hello 123 hello lll sb";
//        String regStr = "hello";
        String regStr = "lll.*";
        Pattern pattern = Pattern.compile(regStr);
        Matcher matcher = pattern.matcher(s);
        while (matcher.find()) {
            System.out.println("=================");
            System.out.println(matcher.start());
            System.out.println(matcher.end());
            System.out.println("找到: " + s.substring(matcher.start(), matcher.end()));
        }
        //整体匹配方法,常用于,去校验某个字符串是否满足某个规则
        System.out.println("整体匹配 = " + matcher.matches());
    }
输出
    start: 16
    end: 19

replaceAll & replaceFirst

  • 作用

    • replaceAll(String replacement):替换所有匹配的子字符串。

    • replaceFirst(String replacement):替换第一个匹配的子字符串。

  • 返回值String,替换后的字符串。

javascript 复制代码
String text = "abc123 def456";
String regex = "\\d+"; // 匹配一个或多个数字
​
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
​
String result1 = matcher.replaceAll("***");
String result2 = matcher.replaceFirst("***");
​
System.out.println("replaceAll: " + result1); // 输出: abc*** def***
System.out.println("replaceFirst: " + result2); // 输出: abc*** def456

find

  • 作用:在输入字符串中查找下一个匹配的子字符串。

  • 返回值boolean,如果找到匹配的子字符串,则返回 true,否则返回 false

  • 特点:可以多次调用,每次查找下一个匹配的子字符串。

    java 复制代码
    String text = "abc123 def456";
    String regex = "\\d+"; // 匹配一个或多个数字
    ​
    Pattern pattern = Pattern.compile(regex);
    Matcher matcher = pattern.matcher(text);
    ​
    while (matcher.find()) {
        System.out.println("找到匹配: " + matcher.group());
    }
    ​
    输出
    找到匹配: 123
    找到匹配: 456

group

  • 作用:返回当前匹配的子字符串。

  • 重载方法

    • group():返回整个匹配的子字符串。

    • group(int group):返回指定分组的子字符串。

    • group(String name):返回命名分组的子字符串(需使用命名分组语法 (?<name>...))。

  • 返回值String,匹配的子字符串。

反向引用

反向引用是正则表达式中的一种功能,用于在同一个正则表达式中引用前面已经捕获的分组内容。通过反向引用,可以匹配与前面分组相同的内容,从而实现更复杂的模式匹配。

反向引用的语法

  • 在正则表达式中,使用 \nn 是分组的编号)来引用第 n 个捕获分组的内容。

  • 分组编号从 1 开始,依次递增。

复制代码
(\w+) \1
  • (\w+):捕获一个或多个字母、数字或下划线,作为第 1 个分组。

  • \1:引用第 1 个分组的内容,要求匹配与第 1 个分组相同的字符串。

反向引用的作用

  • 匹配重复内容:例如,匹配重复的单词、标签等。

  • 验证对称结构:例如,匹配成对的括号、引号等。

  • 简化复杂模式:通过引用分组内容,避免重复编写相同的模式。

java 复制代码
public static void main(String[] args) {
//        String s = "tom5225 jack12 tom11111 mack22 luck33";
        String s = "12321-333999111";
        //匹配两个连续相同的数
//        String regex = "(\\d)\\1";
     //(\\d)该分组用于匹配数字   \\1 
        //匹配五个连续相同的数
//        String regex = "(\\d)\\1{4}";
        //匹配个位与千位相同,十位与百位相同的数
//        String regex = "(\\d)(\\d)\\2\\1";
        /**
         * 检索商品编号,要求前面是一个五位数然后-一个九位数,连续的每三位相同
         */
        String regex = "\\d{5}-(\\d)\\1{2}";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(s);
        while (matcher.find()) {
            System.out.println("找到" + matcher.group(0));
        }
    }

解释一下 (\d)(\d)\2\1

1. 正则表达式结构

  • (\\d):捕获一个数字(0-9),作为第 1 个分组。

  • (\\d):捕获另一个数字,作为第 2 个分组。

  • \\2:反向引用第 2 个分组的内容,要求匹配与第 2 个分组相同的数字。

  • \\1:反向引用第 1 个分组的内容,要求匹配与第 1 个分组相同的数字。


2. 匹配规则

这个正则表达式匹配的四位数字需要满足以下条件:

  1. 第 1 位是任意数字(\\d)。

  2. 第 2 位是任意数字(\\d)。

  3. 第 3 位必须与第 2 位相同(\\2)。

  4. 第 4 位必须与第 1 位相同(\\1)。

反向引用的注意事项

  • 反向引用只能引用前面已经定义的分组。

  • 如果引用的分组不存在,正则表达式会抛出异常或匹配失败。

  • 反向引用的内容必须与分组的内容完全一致。

反向引用学会以后就可以结合replaceAll等方法对字符串进行各种操作

比如

复制代码
将 我....我要....学学学学....编程java! 字符串恢复成正常人说话
java 复制代码
public static void main(String[] args) {
    String s = "我....我要....学学学学....编程java! ";
    s = s.replaceAll("\\.+", "");
    s = s.replaceAll("(.)\\1+", "$1");
    System.out.println(s);
}

spilt

spilt(String regex) 可以传入一个匹配规则,通过这个规则进行分组

java 复制代码
public static void main(String[] args) {
    String s = "hello~lll#qqq";
    String[] split = s.split("~|#|\\d+");
    for (String string : split) {
        System.out.println(string);// hello  lll  qqq
    }
}

底层实现

java 复制代码
package com.hyx.regexp;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author kkwlgs
 * date 2024/10/15 19:39
 * 功能描述:分析正则表达式的底层实现
 */
public class RegTheory {
    public static void main(String[] args) {
        String content = "1234和获取文件的和监控维护的艰苦环境i哦亲黑龙去维护起来换热器然后琼海日哦6546在哦ihi Ohio和hi哦好" +
                "是,二姐琼恩和.u二u琼文i偶你还高1122,饿哦急哦急哦1234.SFS手机hi后11322.";
        //目标: 匹配所有含有四个数字的字符串
        //1. \\d表示任意一个数字
        String regStr = "(\\d\\d)(\\d\\d)";
        //2. 创建模式对象
        Pattern pattern = Pattern.compile(regStr);
        //3. 创建匹配器
        //说明:创建匹配器matcher按照正则表达式规则去匹配
        Matcher matcher = pattern.matcher(content);
        /**
         * match.find() 完成的任务
         * 什么是分组,比如(\d\d)(\d\d),正则表达式中有(),表示分组,第一个()表示第一组,第二个表示第二组
         * 1. 根据指定的规则,定位满足规则得分子字符串
         * 2. 找到后,将子字符串的位置的索引记录到 int[] groups
         *   2.1 groups[0] = 0,把子字符串的结束位置的索引的+1的值记录到groups[1] = 5
         *   2.2 记录1组()匹配到的字符串groups[2] = 0,groups[3] = 2
         *   2.3 记录2组()匹配到的字符串groups[4] = 2,groups[5] = 4
         *   2.4 更多分组.....
         * 3. 同时记录oldLast的值为子字符串的结束的索引+1的值即4,下次执行find时,就从4开始
         *
         * matcher.group
         *        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();
         *         截取groups[0]到groups[1]的值就是从0到4 [0,4)
         *       继续执行match.find()
         */
        //4. 开始匹配
        while (matcher.find()) {
            //小结
            //1. 如果正则表达式有()即分组
            //2. 取出匹配的字符串规则如下
            //3. group(0) 表示匹配到的子字符串
            //4. group(1) 表示匹配到的子字符串的第一组字符串
            //5. group(2) 表示匹配到的子字符串的第二组字符串
            //6. .....但是分组不能超过group(0)的组数
            System.out.println("找到 " + matcher.group(0));
            System.out.println("第一组() " + matcher.group(1));
            System.out.println("第二组() " + matcher.group(2));
        }
    }
}
相关推荐
筑梦之人2 分钟前
Dynamic-Datasource 文档
java
晚安~~9 分钟前
共享充电宝系统|Java|SSM|VUE| 前后端分离
java·开发语言·tomcat·maven
找了一圈尾巴20 分钟前
Wend看源码-Java-Arrays 工具集学习
java·开发语言·学习
HelloZheQ21 分钟前
Java与AI:构建智能应用的强大组合
java·开发语言·人工智能
S-X-S24 分钟前
八万字Java面试高频题目汇总(冲刺春招!)
java·开发语言·面试
Code blocks33 分钟前
小试牛刀-SpringBoot集成SOL链
java·区块链·springboot
Mr。轩。34 分钟前
【Rabbitmq】JAVA的Rabbitmq初步应用随记(安装完成后)
java·rabbitmq·java-rabbitmq
星梦清河38 分钟前
第三部分:微服务01
java·运维·微服务
橘猫云计算机设计1 小时前
基于Django的旅游信息管理系统(源码+lw+部署文档+讲解),源码可白嫖!
java·大数据·hadoop·python·django·旅游
小吕学编程1 小时前
spring防止重复点击,两种注解实现(AOP)
java·后端·spring