Java 中正则表达式的详解

简介: Java 中正则表达式的详解

前言:

Java提供正则表达式技术,专门用于处理文本问题。

简单的说:正则表达式(regular expression) 是对字符串执行模式匹配的技术。

一个正则表达式,就是用某种模式去匹配字符串的一个公式。

一、下面先看一下正则表达式的基本用法:

public class Regexp {
    public static void main(String[] args) {
        String content = "1995年,互联网的蓬勃发展给了Oak机会。业界为了使死板、单调的静态网页能够“灵活”起来,急需一种软件技术来开发一种程序,这种程序可以通过网络传播并且能够跨平台运行。于是,世界各大IT企业为此纷纷投入了大量的人力、物力和财力。这个时候,Sun公司想起了那个被搁置起来很久的Oak,并且重新审视了那个用软件编写的试验平台,由于它是按照嵌入式系统硬件平台体系结构进行编写的,所以非常小,特别适用于网络上的传输系统,而Oak也是一种精简的语言,程序非常小,适合在网络上传输。Sun公司首先推出了可以嵌入网页并且可以随同网页在网络上传输的Applet(Applet是一种将小程序嵌入到网页中进行执行的技术)" +
                ",并将Oak更名为Java(在申请注册商标时,发现Oak已经被人使用了," +
                "再想了一系列名字之后,最终,使用了提议者在喝一杯Java咖啡时无意提到的Java词语)。" +
                "5月23日,Sun公司在Sun world会议上正式发布Java和HotJava浏览器。" +
                "IBM、Apple、DEC、Adobe、HP、Oracle、Netscape和微软等各大公司都纷纷停止了自己的相关开发项目" +
                ",竞相购买了Java使用许可证,并为自己的产品开发了相应的Java平台。";
//        Pattern pattern = Pattern.compile("[a-zA-Z]+"); //提取文章中所有的英文单词
          Pattern pattern = Pattern.compile("[0-9]+"); //提取文章中所有的数字
//        Pattern pattern = Pattern.compile("([0-9]+)|([a-zA-Z]+)"); //提取文章中所有的英文单词和数字
        //创建匹配器
        //说明:创建匹配器matcher,按照正则表达式的规则,去匹配content中的字符串
        Matcher matcher = pattern.matcher(content);
        //理解:matcher匹配器按照pattern(模式/样式),到content文本中去匹配,找到就返回true,否则就返回false
        while (matcher.find()) {
            //匹配内容文本,放到m.group(0)
            System.out.println("找到:" + matcher.group(0));
        }
    }
}

输出文本中所有的数字:

二、正则表达式语法

介绍:如果想要灵活的运用表达式,必须了解其中各种元字符的功能,元字符从功能上大致分为:

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

1.之后首先我们说一下,元字符中的转义符或者说是转义号\ \

在我们使用正则表达式去检索某些特殊字符的时候,需要用到转义符号,否则检索不到结果。

案例代码如下:

public class Regexp02 {
    public static void main(String[] args) {
        String content = "(abc$(abc";
        String regStr = "\\(";
        Pattern pattern = Pattern.compile(regStr);
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            System.out.println("找到:" + matcher.group(0));
        }
    }
}

输出结果:

需要用到的转义符号的字符有以下:. * + ( ) $ / \ ? [ ] ^ { }

2 .接着我们来看字符匹配符都有哪些?

具体的意思也已经给出,大家可以体会一下

下面通过具体的代码来演示一下,具体注释已经在代码中给出了

public class Regexp03 {
    public static void main(String[] args) {
        String content = "a11c8 _abcABC@";
        System.out.println(content);
//        String regStr = "[a-z]"; //匹配a-z之间任意一个字符
//        String regStr = "[A-Z]";//匹配A-Z之间任意一个字符
//        String regStr = "abc"; //匹配abc字符串[默认区分大小写的]
//        String regStr = "(?i)abc"; //匹配abc字符串[不区分大小写的]
//        String regStr = "[0-9]"; //匹配0-9之间任意一个字符
//        String regStr = "[^a-z]"; //匹配不在a-z之间任意一个字符
//        String regStr = "[^0-9]";//匹配不在0-9之间任意一个字符
//        String regStr = "[abcd]";//匹配在abcd中任意一个字符
//        String regStr = "\\D"; //匹配不在0-9的任意一个字符
//        String regStr = "\\w"; //匹配 任意英文字母,数字,下划线
//        String regStr = "\\W"; //匹配 等价于[^a-zA-Z0-9_]
//        String regStr = "\\s"; //匹配 任何空白字符(空格,制表符(就是按下tab键的一个空格))
//        String regStr = "\\S"; //匹配 任何非空白字符,和\\s刚好相反
        String regStr = "."; //匹配除\n 之外的所有字符,如果要匹配.本身则需要使用\\.
        //说明:当创建Pattern对象时,指定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));
        }
    }
}

3 .元字符-选择匹配符

具体案例代码如下,便于理解:

public class Regexp04 {
    public static void main(String[] args) {
        String content = "ha你好 哈 蛤 Java";
        String regStr = "ha|蛤|哈|Java";
        Pattern pattern = Pattern.compile(regStr);
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            System.out.println("找到:" + matcher.group(0));
        }
    }
}

输出结果:

4 .元字符-限定符

用于指定其前面的字符和组合项连续出现多少次

下面通过代码更好的理解一下:

public class Regexp05 {
    public static void main(String[] args) {
        String content = "a21111111aaaaaahello";
//        String regStr = "a{3}"; //表示匹配aaa
//        String regStr = "1{4}"; //表示匹配1111
//        String regStr = "\\d{2}"; //表示匹配 2位的任意数字字符
        //细节:java匹配默认是贪婪匹配,即尽可能匹配多的
//        String regStr = "a{3,4}"; //表示匹配 aaa或者aaaa
//        String regStr = "1{4,5}"; //表示匹配 1111或者11111
//        String regStr = "\\d{2,5}"; //表示匹配 两位数或者三位数,四位数,五位数
//        String regStr = "1+"; //匹配一个1或者多个1
//        String regStr = "\\d+"; //匹配一个数字或者多个数字
//        String regStr = "1*"; //匹配0个1或者多个1
        //演示?的使用,遵守贪婪匹配
        String regStr = "a1?"; //匹配 a 或者 a1
        Pattern pattern = Pattern.compile(regStr);
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            System.out.println("找到:" + matcher.group(0));
        }
    }
}

5 .元字符-定位符

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

下面通过代码更好的理解一下:

/**
 * 演示定位符的使用
 */
public class Regexp06 {
    public static void main(String[] args) {
        String content = "helloworld hihello youhellou";
//        String content = "123-abc";
//        String regStr = "^[0-9]+[a-z]*"; //匹配 以至少1个数字开头,后接任意个小写字母的字符串
//        String regStr = "^[0-9]+[a-z]+$"; //匹配 以至少1个数字开头,必须以至少一个小写字母结束
//        String regStr = "^[0-9]+\\-[a-z]+$"; //匹配 以至少1个数字开头,必须以至少一个小写字母结束,同时中间有一个-
        //表示匹配边界的hello(这里的边界是指:被匹配的字符串最后,也可以是空格的子字符串的后面)
//        String regStr = "hello\\b";
        //和\\b的含义刚好相反
        String regStr = "hello\\B";
        Pattern pattern = Pattern.compile(regStr);
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()){
            System.out.println("找到:"+matcher.group(0));
        }
    }
}

三、正则表达式的分组

1 .捕获分组

下面通过代码更好的理解一下:

public class Regexp07 {
    public static void main(String[] args) {
        String content = "helloJava hi2821 yes2022";
        //下面是非命名分组:
        //说明:
        //1.matcher.group(0)得到匹配到的字符串
        //2.matcher.group(1)得到匹配到的字符串的第一个分组内容
        //3.matcher.group(2)得到匹配到的字符串的第二个分组内容
        //非命名捕获
//        String regStr = "(\\d\\d)(\\d\\d)"; //匹配4个数字的字符串
        //命名分组:即可以给分组取名
        String regStr = "(?<g1>\\d\\d)(?<g2>\\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("g1"));
            System.out.println("第二个分组内容:" + matcher.group(2));
            System.out.println("第二个分组内容[通过组名]:" + matcher.group("g2"));
        }
    }
}

输出结果如下:

2 .非捕获分组

下面通过代码更好的理解一下:

public class Regexp08 {
    public static void main(String[] args) {
        String content = "程序员Android程序员Hello Hi程序员Java程序员 HI程序员Python程序员";
//        String regStr = "Android程序员|Java程序员|Python程序员";
        //上面的写法可以等价为非捕获分组,注意:不能matcher.group(1)
//        String regStr = "程序员(?:Android|Java|Python)";
        //找到程序员这个关键字,但是只要求查找程序员Android,程序员Java
        //下面是非捕获分组,注意:不能matcher.group(1)
//        String regStr = "程序员(?=Android|Java)";
        //找到程序员这个关键字,但是只要求 不查找程序员Android,程序员Java
        //下面是非捕获分组,注意:不能matcher.group(1)
        String regStr = "程序员(?!Android|Java)";
        Pattern pattern = Pattern.compile(regStr);
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            System.out.println("找到:" + matcher.group(0));
        }
    }
}

最后一个输出结果为:

3 .非贪婪匹配

public class Regexp09 {
    public static void main(String[] args) {
        String content = "hello111111 ok";
        //默认是贪婪匹配
//        String regStr = "\\d+";
        //非贪婪匹配
        String regStr = "\\d+?";
        Pattern pattern = Pattern.compile(regStr);
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            System.out.println("找到:" + matcher.group(0));
        }
    }
}

输出结果:

下面我们通过正则表达式的几个应用案例,来进行灵活运用。

public class Regexp10 {
    public static void main(String[] args) {
//        String content = "Java开发工程师";
        String content = "13682153694";
        //汉字
//        String regStr = "^[\u0391-\uffe5]+$";
        //邮政编码
        //要求:是1-9开头的6位数,比如123490
//        String regStr = "^[1-9]\\d{5}$";
        //QQ号码
        //要求:是1-9开头的一个(5位数-10位数) 比如:12345,4521361
//        String regStr = "^[1-9]\\d{4,9}$";
        //手机号码
        //要求:必须以13,14,15,18开头的11位数,比如13682153694
        String regStr = "^1[3|4|5|8]\\d{9}$";
        Pattern pattern = Pattern.compile(regStr);
        Matcher matcher = pattern.matcher(content);
        if (matcher.find()) {
            System.out.println("满足格式");
        } else {
            System.out.println("不满足格式");
        }
    }

下面是通过正则表达式验证复杂的url,代码如下:

public class Regexp11 {
    public static void main(String[] args) {
        /**
         *演示正则表达式的使用
         */
        String content = "https://blog.csdn.net/lu202032/article/details/122136115?spm=1001.2014.3001.5501";
        /**
         * 思路:
         * 1.先确定url开始的部分,https:// | http://
         * 2.然后通过([\w-]+\.)+[\w-]+ 匹配blog.csdn.net
         * 3. /lu202032/article/details/122136 匹配(\/[\w-?&=/%.]*)?
         */
        String regStr = "^((https|https)://)([\\w-]+\\.)+[\\w-]+(\\/[\\w-?&=/%.]*)?$"; //注意:[.]表示匹配的就是.本身
        Pattern pattern = Pattern.compile(regStr);
        Matcher matcher = pattern.matcher(content);
        if (matcher.find()) {
            System.out.println("满足格式");
        } else {
            System.out.println("不满足格式");
        }
    }
}

接下来我们再讲解一下,正则表达式的三个常用类

  1. Pattern类:pattern对象是一个正则表达式对象,Pattern类没有公共构造方法,创建一个Pattern对象,需要调用公共静态方法,它返回一个Pattern对象,该方法接受一个正则表达式作为它的第一个参数。
  2. Matcher类:Matcher对象是对输入字符串进行解释和匹配的引擎。与Pattern类一样,Matcher也没有构造方法,你需要调用Pattern对象的matcher方法来获得一个Matcher对象。
  3. PatternSyntaxException类:是一个非强制异常类,它表示一个正则表达式模式中的语法错误。

下面我们来演示Pattern类中的matches()

public class Regexp12 {
    public static void main(String[] args) {
        //演示matches方法,用于整体匹配,用来验证输入的字符串是否满足条件使用
        String content = "hello abc hello,Java开发";
//        String regStr = "hello"; //false
        String regStr = "hello.*";
        boolean matchers = Pattern.matches(regStr, content);
        System.out.println("整体匹配:" + matchers);
    }
}

下面是Matcher类中常用的方法说明:

通过代码演示几个常用的方法,加深理解:

public class MatcherMethod {
    public static void main(String[] args) {
        String content = "hello edu jack tom hello smith hello";
        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有hello替换成Java
        regStr = "hello";
        pattern = Pattern.compile(regStr);
        matcher = pattern.matcher(content);
        String newContent = matcher.replaceAll("Java");
        System.out.println("newContent:" + newContent);
        System.out.println("content:" + content);
    }
}

下面介绍一下反向引用的概念

下面是反向引用的案例,代码如下:

public class Regexp13 {
    public static void main(String[] args) {
        String content = "hello jack14 tom11111 j12321-333999111ack2232 yyy xxx2552";
        //找到两个相同的数字
//        String regStr = "(\\d)\\1";
        //匹配五个相同的数字
//        String regStr = "(\\d)\\1{4}";
        //匹配个位与千位相同,十位与百位相同的数,5225,1551
//        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));
        }
    }
}

以上就是正则表达式的详解,如果有不当之处,还望各位加以指正~


目录
相关文章
|
14天前
|
监控 Java Python
Java 中的正则表达式
正则表达式是Java中强大的文本处理工具,支持灵活的匹配、搜索、替换和验证功能。本文介绍了正则表达式的语法基础及其在Java中的应用,包括字符串匹配、替换、分割及实际场景中的邮箱验证和电话号码提取等示例。通过这些技术,可以显著提高文本处理的效率和准确性。
57 8
|
17天前
|
Java API 开发者
Java中的Lambda表达式与Stream API的协同作用
在本文中,我们将探讨Java 8引入的Lambda表达式和Stream API如何改变我们处理集合和数组的方式。Lambda表达式提供了一种简洁的方法来表达代码块,而Stream API则允许我们对数据流进行高级操作,如过滤、映射和归约。通过结合使用这两种技术,我们可以以声明式的方式编写更简洁、更易于理解和维护的代码。本文将介绍Lambda表达式和Stream API的基本概念,并通过示例展示它们在实际项目中的应用。
|
19天前
|
Java API 开发者
Java中的Lambda表达式:简洁代码的利器####
本文探讨了Java中Lambda表达式的概念、用途及其在简化代码和提高开发效率方面的显著作用。通过具体实例,展示了Lambda表达式如何在Java 8及更高版本中替代传统的匿名内部类,使代码更加简洁易读。文章还简要介绍了Lambda表达式的语法和常见用法,帮助开发者更好地理解和应用这一强大的工具。 ####
|
21天前
|
并行计算 Java 编译器
深入理解Java中的Lambda表达式
在Java 8中引入的Lambda表达式,不仅简化了代码编写,还提升了代码可读性。本文将带你探索Lambda表达式背后的逻辑与原理,通过实例展示如何高效利用这一特性优化你的程序。
|
25天前
|
搜索推荐 Java API
探索Java中的Lambda表达式
本文将深入探讨Java 8引入的Lambda表达式,这一特性极大地简化了代码编写,提高了程序的可读性。通过实例分析,我们将了解Lambda表达式的基本概念、使用场景以及如何优雅地重构传统代码。文章不仅适合初学者,也能帮助有经验的开发者加深对Lambda表达式的理解。
|
1月前
|
Java
探索Java中的Lambda表达式
【10月更文挑战第37天】本文将带你深入理解Java的Lambda表达式,从基础语法到高级特性,通过实例讲解其在函数式编程中的应用。我们还将探讨Lambda表达式如何简化代码、提高开发效率,并讨论其在实际项目中的应用。
|
1月前
|
Java API
Java中的Lambda表达式与函数式编程####
【10月更文挑战第29天】 本文将深入探讨Java中Lambda表达式的实现及其在函数式编程中的应用。通过对比传统方法,我们将揭示Lambda如何简化代码、提高可读性和维护性。文章还将展示一些实际案例,帮助读者更好地理解和应用Lambda表达式。 ####
|
1月前
|
JSON 自然语言处理 Java
这款轻量级 Java 表达式引擎,真不错!
AviatorScript 是一个高性能、轻量级的脚本语言,基于 JVM(包括 Android 平台)。它支持数字、字符串、正则表达式、布尔值等基本类型,以及所有 Java 运算符。主要特性包括函数式编程、大整数和高精度运算、完整的脚本语法、丰富的内置函数和自定义函数支持。适用于规则判断、公式计算、动态脚本控制等场景。
|
16天前
|
安全 Java API
Java中的Lambda表达式:简化代码的现代魔法
在Java 8的发布中,Lambda表达式的引入无疑是一场编程范式的革命。它不仅让代码变得更加简洁,还使得函数式编程在Java中成为可能。本文将深入探讨Lambda表达式如何改变我们编写和维护Java代码的方式,以及它是如何提升我们编码效率的。
|
18天前
|
安全 Java API
Java中的Lambda表达式与Stream API的高效结合####
探索Java编程中Lambda表达式与Stream API如何携手并进,提升数据处理效率,实现代码简洁性与功能性的双重飞跃。 ####
24 0