10-正则表达式

发布于:2025-08-12 ⋅ 阅读:(15) ⋅ 点赞:(0)

一 正则表达式简介

正则表达式(Regular Expressions),是一个特殊的字符串,可以对普通的字符串进行校验检测等工作。正则表达式不是Java特有的,它是一套独立的语法,可以在java,c++,python等语言中使用。

正则表达式,最基本的使用场景是用来做校验,校验一个字符串是否满足预设的规则。在校验的基础 上,又添加了若干个其他的引用场景,例如: 批量的查找、替换、切割...

二 正则表达式语法

2.1 字符串中常用方法

字符串类型中提供了几个与正则表达式相关的方法

序号

方法名以及返回值类型

解析

boolean matches(String regex)

判断this字符串是否匹配正则表达式regex

String[] split(String regex)

对this使用匹配上正则表达式的子串进行切分成字符串数组

replaceAll(String regex, String replacement)

将一个字符串中的所有的满足正则规则部分的字符串,替换成指定的字符串

replaceFirst(String regex, String replacement)

将一个字符串中的第一个满足正则规则部分的字符串,替换成指定的字符串

2.2 字符集语法

表达式

解析

[]

表示匹配括号里的任意一个字符。

[abc]

字符集。匹配a 或者 b 或者 c

[^abc]

反向字符集。

[a-g]

字符范围。表示匹配所有的小写字母的任意一个。

[^a-z]

反向字符范围。匹配不在指定的范围内的任何字符。例如,"[^a-z]"匹配任何不在"a"到"z"范围内的任何字符。

[A-Za-z]

表示匹配所有的小写字母和大写字母的任意一个。

[a-zA-Z0-9]

表示匹配所有的小写字母和大写字母和数字的任意一个。

[a-z&&[^bc]]

表示匹配所有的小写字母除了b和c, 只要匹配上就是true.

\d

用于匹配数字字符中的任意一个 相当于[0-9]

\D

用于匹配非数字字符中的任意一个 相当于[^0-9]

\w

匹配单词字符中的任意一个 单词字符就是[a-zA-Z0-9_]

\W

用于匹配非单词字符中的任意一个

\s

用于匹配空格,制表符,退格符,换行符等中的任意一个

\S

用于匹配非空格,制表符,退格符,换行符等中的任意一个

.

用于匹配任意一个字符

2.3 量词语法

X?

匹配0个或1个

X*

匹配0个或1个以上

x+

匹配1个以上

X{n}

匹配n个

X{m,}

匹配m个以上

X{m,n}

匹配m~n个

2.4 分组语法

()

在正则表达式上可以使用()来进行对一些字符分组,并可以使用逻辑运算符|来进行选择匹配

reg: String regex = "(135|137)[\\d]{8}" //匹配手机号是135或者是137开头的

2.5 ^和$

^

表示严格从头匹配

$

表示匹配到结尾

三 Pattern的简介

其实,Pattern这个类,才是真正来操作正则表达式的类,它位于java.util.regex包下。在String类中的提供的 matches 、split 、replace等方 法,其实都是对这个类中的某些方法的封装。

在我们调用String类中的提供的 matches 、split 、replace等方法时,底层就会创建一个Pattern对象。这样的做法效率是很低的。我们何不主动创建一个pattern,然后每次需要匹配就直接用它而不需要再次创建,大大提高了程序的效率。

常用方法如下:

  1. static Pattern complie(String regex)

Pattern类的构造方法是私有的,不可以直接创建,但可以通过Pattern.complie(String regex)简单工厂方法创建一个正则表达式,

如: Pattern p=Pattern.compile("\\w+");

  1. pattern()

返回正则表达式的字符串形式,其实就是返回Pattern.complile(String regex)的regex参数

Pattern p=Pattern.compile("\\w+"); 
String regex = p.pattern();//返回 \w+ 
  1. matcher(String str)

返回一个Matcher类型的对象。

Matcher matcher = p.matcher("michael");

四 Matcher类

Pattern类只能做一些简单的匹配操作,要想得到更强更便捷的正则匹配操作,那就需要将Pattern与Matcher一起合作.Matcher类提供了对正则表达式的分组支持,以及对正则表达式的多次匹配支持。简单来说,Matcher对象就是Pattern对象与字符串匹配的一个结果。

4.1 Matcher对象的获取

Matcher的构造方法是私有的,我们一般通过调用Pattern对象的matcher方法返回一个matcher。


String info = "名字:wulei  地址:hunan  电话:010-82350555";
Pattern p = Pattern.compile("(名字:\\w+\\s+)|(地址:\\w+\\s+)|(电话:\\d{3}-\\d{8})");
Matcher matcher = p.matcher(info);

4.2 Matcher类型的匹配方法

Matcher对象提供了三个不同的匹配方式:matches、 lookingAt()、find()。三个方法均返回boolean类型,当匹配到时返回true,没匹配到则返回false

  1. boolean matches()

     
    String info = "123abc";
    Pattern p = Pattern.compile("\\d+");
    Pattern p1 = Pattern.compile("\\d+\\w+");
    Matcher matcher = p.matcher(info);
    Matcher matcher1 = p1.matcher(info);
    
    System.out.println(matcher.matches());//false
    System.out.println(matcher1.matches());//true
     
    1. 整个字符串必须符合正则表达式,才会返回true,否则返回false

  2. boolean lookingAt()

    System.out.println(matcher.lookingAt()); //true、
    字符串的开头符合使用的正则表达式,返回true。否则返回false
    String info = "123abc456def789";
    Pattern p = Pattern.compile("\\d+");
    Matcher matcher = p.matcher(info);
    while(matcher.find()){
        System.out.println(matcher.group());
    }
    输出:
    123
    456
    789
  3. reset()

    重置find()的指针。注意:lookingAt()会影响到find()查找的子字符串
    String info = "123abc456def789";
    Pattern p = Pattern.compile("\\d+");
    Matcher matcher = p.matcher(info);
    System.out.println("执行lookingAt()后的group:");
    matcher.lookingAt();
    System.out.println(matcher.group());
    //matcher.reset();
    System.out.println("执行find():");
    while(matcher.find()){
       System.out.println(matcher.group());
    }
    
    输出:
       执行lookingAt()后的group:
    123
       执行find():
    456
    789

4.3 Matcher类型的详情方法

当我们执行完匹配操作后,我们常常需要获得匹配到的具体字符串。matcher对象能够使用group()、start()、end()方法来获取相关信息。

注意:这三个方法是基于我们matcher执行matches()|lookingAt()|find()并匹配成功的情况下才能使用,否则会抛出java.lang.IllegalStateException

  1. group()

    返回匹配到的子字符串
  2. group(int index)

    返回匹配到的子字符串里的第index个分组,group(0)=group()。
  3. start()

    返回匹配到的子字符串在字符串中的索引位置
  4. start(int index)

    返回匹配到的子字符串里的第index个分组开始的索引。
  5. end()

    返回匹配到的子字符串的最后一个字符在字符串中的索引位置+1
  6. end(int index)

      现在我们使用一下稍微高级点的正则匹配操作,例如有一段文本,里面有很多数字,而且这些数字是分开的,我们现在要将文本中所有数字都取出来,利用java的正则操作是那么的简单
    
    String info = "123abc456def789";
    Pattern p = Pattern.compile("(\\d+)([a-z]+)");
    Matcher matcher = p.matcher(info);
    
    while (matcher.find()){
        System.out.println("start(1): " + matcher.start(1));
            System.out.println("start(2): " + matcher.start(2));
            System.out.println("end(1): " + matcher.end(1));
            System.out.println("end(2): " + matcher.end(2));
    }
    
    输出:
    start(1): 0
    start(2): 3
    end(1): 3
    end(2): 6
    start(1): 6
    start(2): 9
    end(1): 9
    end(2): 12
    

    .

    返回匹配到的子字符串里的第index个分组结束的索引+1。
    
    Pattern p=Pattern.compile("\\d+"); 
    Matcher m=p.matcher("我的QQ是:456456 我的电话是:0532214 我的邮箱是:aaa123@aaa.com"); 
    while(m.find()) { 
         System.out.println(m.group()); 
    } 
    
    输出: 
    456456 
    0532214 
    123 
    
    如将以上while()循环替换成 
    while(m.find()) { 
         System.out.println(m.group()); 
         System.out.print("start:"+m.start()); 
         System.out.println(" end:"+m.end()); 
    } 
    则输出: 
    456456 
    start:6 end:12 
    0532214 
    start:19 end:26 
    123 
    start:36 end:39 

  7. int groupCount()

    1.用于获取正则表达式中的小括号的个数。() 用于分组。
    
    package com.se.day02.bPattern;
    
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    /**
     * 研究一下groupCount():
     */
    public class PatternDemo07Matcher05 {
        public static void main(String[] args) {
            Pattern pattern = Pattern.compile("(((c)a)(t))s");
            Matcher matcher = pattern.matcher("one cat, two cats in the yard");
            /**
             * int groupCount():
             * 作用:用于获取正则表达式中的小括号的个数。() 用于分组。
             */
            System.out.println(matcher.groupCount());
            while (matcher.find()) {
                // 打印符合正则表达式的子串, 因此循环次数是xxxx次。
                System.out.println(matcher.group());
            }
            /**
             * 使用小括号的个数来循环, 可以使用group的重载方法:
             * String group(int group)
             *
             * 注意:想要使用()的个数进行遍历,需要将指针移动到字符串之前,然后还需要调用一下find方法
             *
             * group(0): 表示的是对组进行拆分括号的整体的样子
             * group(1): 表示第一个括号
             * group(2): 表示第二个括号
             */
            matcher.reset();
            matcher.find();
            for (int i = 0; i <=matcher.groupCount(); i++) {
                System.out.println(matcher.group(i));
            }
        }
    }

五 练习题以及八股文

  1. 邮箱验证

      编写一个方法,使用正则表达式验证邮箱地址格式是否正确。要求:用户名可以包含字母、数字、点、下划线和连字符,域名包含至少一个点,且顶级域名至少2个字符。

    1. 手机号码验证

    编写一个方法验证中国大陆手机号码格式(11位数字,以1开头,第二位为3-9)。使用正则表达式实现。

    1. 密码强度检查

    创建一个方法检查密码强度,要求:

    • 至少8位字符

    • 包含至少一个大写字母

    • 包含至少一个小写字母

    • 包含至少一个数字

    • 包含至少一个特殊字符(!@#$%^&*)

    1. 提取URL信息

    编写程序从文本中提取所有的URL链接,并分别提取协议、域名和路径部分。使用正则表达式的分组捕获功能。

    1. HTML标签处理

        编写一个方法,使用正则表达式移除字符串中的所有HTML标签,但保留标签内的文本内容。

      1. 日期格式验证与提取

      编写程序验证并提取文本中的日期(支持yyyy-MM-dd、yyyy/MM/dd、dd-MM-yyyy等格式),并将它们转换为统一的yyyy-MM-dd格式。

      1. 单词边界匹配

      编写一个方法,使用正则表达式查找文本中完整单词"java"(不匹配"javascript"中的"java"),并统计出现次数。

      1. IP地址验证

          编写一个方法验证IPv4地址格式是否正确(0-255之间的数字,用点分隔)。要求使用正则表达式的前瞻断言功能。

        1. 字符串格式化处理

            编写程序处理文本,将连续的空白字符(空格、制表符、换行符)替换为单个空格,并去除行首行尾空白。

          1. 复杂数据解析

              给定一个包含姓名、年龄、邮箱的文本文件,每行格式如:"张三,25,zhangsan@example.com",使用正则表达式解析并验证每行数据的正确性,将有效数据存储到对象列表中。


            网站公告

            今日签到

            点亮在社区的每一天
            去签到