一文学会java正则表达式

简介: 1.什么是正则表达式?在了解正则表达式之前,我们先看几个非常常见的问题:如何判断字符串是否是有效的电话号码?例如:010-1234567,123ABC456,13510001000等;如何判断字符串是否是有效的电子邮件地址?例如:test@example.com,test#example等;如何判断字符串是否是有效的时间?例如:12:34,09:60,99:99等。一种直观的想法是通过程序判断,这种方法需要为每种用例创建规则,然后用代码实现。为每一种判断逻辑编写代码实在是太繁琐了。有没有更简单的方法?


1.什么是正则表达式?


在了解正则表达式之前,我们先看几个非常常见的问题:

如何判断字符串是否是有效的电话号码?例如:010-1234567,123ABC456,13510001000等;

如何判断字符串是否是有效的电子邮件地址?例如:test@example.com,test#example等;

如何判断字符串是否是有效的时间?例如:12:34,09:60,99:99等。

一种直观的想法是通过程序判断,这种方法需要为每种用例创建规则,然后用代码实现。

为每一种判断逻辑编写代码实在是太繁琐了。有没有更简单的方法?

有!用正则表达式!

正则表达式可以用字符串来描述规则,并用来匹配字符串。例如,判断手机号,我们用正则表达式\d{11}

使用正则表达式的好处有哪些?一个正则表达式就是一个描述规则的字符串,所以,只需要编写正确的规则,我们就可以让正则表达式引擎去判断目标字符串是否符合规则。

正则表达式是一套标准,它可以用于任何语言。Java标准库的java.util.regex包内置了正则表达式引擎,在Java程序中使用正则表达式非常简单。


2.快速入门案例


找到文本中的所有英文单词(含字母):


import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * 正则表达式快速入门
 */
public class HelloRegularExpression {
    public static void main(String[] args) {
        String content = "Go的语法接近C语言,但对于变量的声明有所不同。Go支持垃圾回收功能" +
                "。Go的并行模型是以东尼·霍尔的通信顺序进程(CSP)为基础,采取类似模型的" +
                "其他语言包括Occam和Limbo,但它也具有Pi运算的特征,比如通道传输。在" +
                "1.8版本中开放插件(Plugin)的支持,这意味着现在能从Go中动态加载部分" +
                "函数。\n" +
                "与C++相比,Go并不包括如枚举、异常处理、继承、泛型、断言、虚函数等功" +
                "能,但增加了 切片(Slice) 型、并发、管道、垃圾回收、接口" +
                "(Interface)等特性的语言级支持。Go 2.0版本将支持泛型,对于断言的" +
                "存在,则持负面态度,同时也为自己不提供类型继承来辩护。\n" +
                "不同于Java,Go内嵌了关联数组(也称为哈希表(Hashes)或字典" +
                "(Dictionaries) ),就像字符串类型一样。";
        // 实例:找到文本中的所有英文单词(含字母)
        // 先创建一个Pattern模式对象
        Pattern pattern = Pattern.compile("[a-zA-Z]+");
        // 创建一个匹配器对象
        Matcher matcher = pattern.matcher(content);
        // 开始匹配
        while (matcher.find()) {
            System.out.println("找到:" + matcher.group(0));
        }
    }
}
-------------------------------
输出:
找到:Go
找到:C
找到:Go
找到:Go
找到:CSP
找到:Occam
找到:Limbo
找到:Pi
找到:Plugin
找到:Go
找到:C
找到:Go
找到:Slice
找到:Interface
找到:Go
找到:Java
找到:Go
找到:Hashes
找到:Dictionaries


3.正则表达式语法


转义符号🙌


当我们在检索某些字符时,需要用到转义符号,否则检索不到结果,甚至发生错误❌

在正则表达式中,两个\\代表其他语言中的一个\


字符匹配符🧂


[]   - 可接受的字符列表


[efgh] 表示可接收的efgh中的任意一个字符


[^]   - 不可接受的字符列表


^abc 表示除了abc之外的任意一个字符,包括数字和特殊字符


-   - 连字符


A-Z 表示任意一个大写字母


.   - 匹配除\n以外的任意一个字符


a..b 以a开头,b结尾,中间包括2个任意字符的长度为4的字符串


\\d   - 匹配单个数字字符


\\d{3}(\\d)? 包含3个或者4个数字的字符串


\\D 匹配单个非数字字符


\D(\\d)* 以单个非数字字符开头,后接任意个数字字符串


\\w 匹配单个数字、大小写字符


\\d{3}\\w{4} 以三个数字字符开头的长度为7的数字字母字符串


\\W 匹配非数字字母字符串


\\W+\\d{2} 以至少一个非数字字母字符开头,2个数字字符结尾的字符串


字符匹配符演示🤞


import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * 正则表达式快速入门
 */
public class HelloRegularExpression {
    public static void main(String[] args) {
        String content = "Go的语法接近C语言,但对于变量的声明有所不同。Go支持垃圾回收功能" +
                "。Go的并行模型是以东尼·霍尔的通信顺序进程(CSP)为基础,采取类似模型的" +
                "其他语言包括Occam和Limbo,但它也具有Pi运算的特征,比如通道传输。在" +
                "1.8版本中开放插件(Plugin)的支持,这意味着现在能从Go中动态加载部分" +
                "函数。\n" +
                "与C++相比,Go并不包括如枚举、异常处理、继承、泛型、断言、虚函数等功" +
                "能,但增加了 切片(Slice) 型、并发、管道、垃圾回收、接口" +
                "(Interface)等特性的语言级支持。Go 2.0版本将支持泛型,对于断言的" +
                "存在,则持负面态度,同时也为自己不提供类型继承来辩护。\n" +
                "不同于Java,Go内嵌了关联数组(也称为哈希表(Hashes)或字典" +
                "(Dictionaries) ),就像字符串类型一样。a11c8abcABCaBc";
        // 实例:找到文本中的所有英文单词(含字母)
        // 先创建一个Pattern模式对象
        Pattern pattern = Pattern.compile("[a-zA-Z]+");
        // 创建一个匹配器对象
        Matcher matcher = pattern.matcher(content);
        // 开始匹配
        while (matcher.find()) {
            System.out.println("找到:" + matcher.group(0));
        }
        // 实例:找到a-z之间的任意一个字符
        Pattern pattern1 = Pattern.compile("[a-z]");
        Matcher matcher1 = pattern1.matcher(content);
        while (matcher1.find()) {
            System.out.println("2找到:" + matcher1.group(0));
        }
        // 实例:找到abc字符,不区分大小写
        Pattern pattern2 = Pattern.compile("(?i)abc");
        Matcher matcher2 = pattern2.matcher(content);
        while (matcher2.find()) {
            System.out.println("3找到:" + matcher2.group(0));
        }
        // 实例:找到abc字符,b不区分大小写
        Pattern pattern3 = Pattern.compile("a((?i)b)c");
        Matcher matcher3 = pattern3.matcher(content);
        while (matcher3.find()) {
            System.out.println("4找到:" + matcher3.group(0));
        }
        // 实例:找到abc字符,不区分大小写,设置参数的方式
        Pattern pattern4 = Pattern.compile("abc", Pattern.CASE_INSENSITIVE);
        Matcher matcher4 = pattern4.matcher(content);
        while (matcher4.find()) {
            System.out.println("5找到:" + matcher4.group(0));
        }
        // 实例:找到非数字字母字符的所有字符(含中文)
        Pattern pattern5 = Pattern.compile("\\W", Pattern.CASE_INSENSITIVE);
        Matcher matcher5 = pattern5.matcher(content);
        while (matcher5.find()) {
            System.out.println("6找到:" + matcher5.group(0));
        }
    }
}


选择匹配符🎈


|   - 多个条件满足一个即可匹配成功


例如:匹配文本中的Go/C/Java中的任意一个字符串


String content = "Go的语法接近C语言,但对于变量的声明有所不同。Go支持垃圾回收功能" +
        "。Go的并行模型是以东尼·霍尔的通信顺序进程(CSP)为基础,采取类似模型的" +
        "其他语言包括Occam和Limbo,但它也具有Pi运算的特征,比如通道传输。在" +
        "1.8版本中开放插件(Plugin)的支持,这意味着现在能从Go中动态加载部分" +
        "函数。\n" +
        "与C++相比,Go并不包括如枚举、异常处理、继承、泛型、断言、虚函数等功" +
        "能,但增加了 切片(Slice) 型、并发、管道、垃圾回收、接口" +
        "(Interface)等特性的语言级支持。Go 2.0版本将支持泛型,对于断言的" +
        "存在,则持负面态度,同时也为自己不提供类型继承来辩护。\n" +
        "不同于Java,Go内嵌了关联数组(也称为哈希表(Hashes)或字典" +
        "(Dictionaries) ),就像字符串类型一样。a11c8abcABCaBc";
Pattern pattern = Pattern.compile("Go|C|Java");
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
    System.out.println("找到:" + matcher.group(0));
}


正则限定符😶‍🌫️


*   - 指定字符重复0次或n次


示例:(abc)* 指定abc字符串重复0次或者n次

实例:abc,abcabcabc


+   - 指定字符重复1次或n次


示例:m+(abc)* 指定以至少一个m开头,后面接任意个abc的字符串

实例:m,mabc,mmabcabc


?   - 指定字符重复0次或者1次


示例:m+abc? 指定以至少一个m开头,后面是ab或者abc的字符串

实例:mab,mmabc


{n}   - 只能输入n个字符


示例:[abcd]{3} 由abcd字符组成的任意长度为3的字符串

实例:abc,dbc,adc


{n,}   - 指定至少n个匹配


示例:[abcd]{3,} 由abcd组成的任意长度不小于3的字符串

实例:aab,aaadbc


{n,m}   - 指定至少n个但是不多于m个匹配
注意:java的匹配是贪婪匹配,即尽可能匹配多的,即优先匹配m个字符


示例:[abcd]{3,5} 由abcd组成的任意长度不小于3大于5的字符串

实例:abc,aaabb

代码演示:(匹配六个a)


import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * 正则限定符
 */
public class Qualifier {
    public static void main(String[] args) {
        String content = "Go的语法接近C语言,但对于变量的声明有所不同。Go支持垃圾回收功能" +
                "。Go的并行模型是以东尼·霍尔的通信顺序进程(CSP)为基础,采取类似模型的" +
                "其他语言包括Occam和Limbo,但它也具有Pi运算的特征,比如通道传输。在" +
                "1.8版本中开放插件(Plugin)的支持,这意味着现在能从Go中动态加载部分" +
                "函数。\n" +
                "与C++相比,Go并不包括如枚举、异常处理、继承、泛型、断言、虚函数等功" +
                "能,但增加了 切片(Slice) 型、并发、管道、垃圾回收、接口" +
                "(Interface)等特性的语言级支持。Go 2.0版本将支持泛型,对于断言的" +
                "存在,则持负面态度,同时也为自己不提供类型继承来辩护。\n" +
                "不同于Java,Go内嵌了关联数组(也称为哈希表(Hashes)或字典" +
                "(Dictionaries) ),就像字符串类型一样。aaaaaa11c8abcABCaBc";
        // 匹配六个a
        Pattern pattern = Pattern.compile("a{6}");
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            System.out.println("找到:" + matcher.group(0));
        }
    }
}


正则定位符🎶


^   - 指定起始字符


示例:^[0-9]+[a-z]* 以至少1个数字开头,后接任意个小写字母的字符串

实例:123,6aa,555edf


$   - 指定结束字符


示例:^[0-9]\\-[a-z]+$ 以至少一个数字开头连接-并以至少一个小写字母结尾的字符串

实例:1-a,2-abc

程序演示:


Pattern pattern = Pattern.compile("^[0-9]+[a-z]*");
Matcher matcher = pattern.matcher("123abc");
while (matcher.find()) {
    System.out.println("找到:" + matcher.group(0));
}
Pattern pattern2 = Pattern.compile("^[0-9]\\-[a-z]+$");
Matcher matcher2 = pattern2.matcher("1-a");
while (matcher2.find()) {
    System.out.println("找到:" + matcher2.group(0));
}
------------------------------------------------
输出:
找到:123abc
找到:1-a


\\b   - 匹配目标字符串的边界(结尾)


示例:guo\\B 字串间有空格,或者是目标字符串的开头位置匹配guo


实例:guoyunyun guotime

目录
相关文章
|
3月前
|
安全 Java API
Java中的Lambda表达式:简洁与功能的结合
Java中的Lambda表达式:简洁与功能的结合
371 211
|
3月前
|
安全 Java
Java中的Switch表达式:更简洁的多路分支
Java中的Switch表达式:更简洁的多路分支
458 211
|
24天前
|
Java Go 开发工具
【Java】(8)正则表达式的使用与常用类分享
正则表达式定义了字符串的模式。正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别。
149 2
|
3月前
|
Java 编译器 API
Java Lambda表达式与函数式编程入门
Lambda表达式是Java 8引入的重要特性,简化了函数式编程的实现方式。它通过简洁的语法替代传统的匿名内部类,使代码更清晰、易读。本文深入讲解Lambda表达式的基本语法、函数式接口、方法引用等核心概念,并结合集合操作、线程处理、事件回调等实战案例,帮助开发者掌握现代Java编程技巧。同时,还解析了面试中高频出现的相关问题,助你深入理解其原理与应用场景。
|
4月前
|
自然语言处理 Java Apache
在Java中将String字符串转换为算术表达式并计算
具体的实现逻辑需要填写在 `Tokenizer`和 `ExpressionParser`类中,这里只提供了大概的框架。在实际实现时 `Tokenizer`应该提供分词逻辑,把输入的字符串转换成Token序列。而 `ExpressionParser`应当通过递归下降的方式依次解析
279 14
|
3月前
|
Java 编译器
Java 17 Switch表达式:更简洁、更强大的流程控制
Java 17 Switch表达式:更简洁、更强大的流程控制
|
4月前
|
设计模式 数据采集 Java
Java正则表达式的基础知识,进阶至熟练掌握。
通过大量的练习来熟悉它们的识别模式、如何设计模式来解决实际问题,才能够逐步达到熟练掌握。更多的是通过实践、编写代码和解决真实问题来完善技能。在这方面,没有快速的捷径,唯有刻意练习和长时间的代码实践。
89 0
|
5月前
|
SQL JSON 安全
Java 8 + 中 Lambda 表达式与 Stream API 的应用解析
摘要:本文介绍了Java 8+核心新特性,包括Lambda表达式与Stream API的集合操作(如过滤统计)、函数式接口的自定义实现、Optional类的空值安全处理、接口默认方法与静态方法的扩展能力,以及Java 9模块化系统的组件管理。每个特性均配有典型应用场景和代码示例,如使用Stream统计字符串长度、Optional处理Map取值、模块化项目的依赖声明等,帮助开发者掌握现代Java的高效编程范式。(150字)
98 1
|
7月前
|
缓存 监控 Java
深入解析java正则表达式
本文深入解析Java正则表达式的应用,从基础概念到实际开发技巧全面展开。正则表达式是一种强大的文本处理工具,广泛应用于格式验证、搜索替换等场景。Java通过`Pattern`和`Matcher`类支持正则表达式,`Pattern.compile()`方法将正则字符串编译为高效模式对象。文章详细介绍了核心类的功能、常用正则语法及实际案例(如邮箱和电话号码验证)。掌握这些内容,可显著提升文本处理能力,满足多种开发需求。
234 1