JAVA

一文讲透 Java Regex正则表达式!

转载:一文讲透 Java Regex正则表达式!

正则表达式是一种用于描述字符串模式的工具,它在文本处理、数据验证、搜索和替换等方面有着广泛的应用。这篇文章,我们将分析什么是正则表达式以及它是如何工作的?

什么是正则表达式?


正则表达式(regular expression,常简写为 regex、regexp 或 RE),又称规律表达式、正规表示式、正规表示法、规则运算式、常规表示法,是计算机科学概念,用简单字串来描述、匹配文中全部符合指定格式的字串,現在很多文本编辑器都支援用正则表达式搜寻、取代符合指定格式的字串。

Java Regex是一种用于匹配字符串的模式,它可以用来验证、查找、替换或拆分字符串。Java中的正则表达式由 java.util.regex包提供,主要由 3 个类和 1 个接口组成:

  • Pattern Class:表示正则表达式的编译表示。
  • Matcher Class:用于执行匹配操作的引擎。
  • PatternSyntaxException Class:表示正则表达式语法错误的异常。
  • MatchResult Interface:用于表示匹配操作的结果。

正则表达式组成


Java 正则表达式主要由以下几部分组成:

  • 字符类:用于匹配指定范围内的任意字符。例如[a-z]表示匹配任意小写字母。
  • 预定义字符类:简化的字符类。例如\d表示匹配任意数字,\w表示匹配任意字母、数字或下划线。
  • 量词:用于指定字符或子表达式的重复次数。例如a*表示匹配零次或多次 a,a{2,4}表示匹配 2 到 4 次 a。
  • 边界匹配符:用于匹配字符串的边界。例如^表示匹配字符串的开始,$表示匹配字符串的结束。
  • 分组:用于将多个字符或子表达式组合在一起。例如(abc)表示匹配字符串 “abc”。

下面还列举了一些常见的正则表达式元素:

  • .: 匹配除换行符以外的任意单字符
  • *: 匹配前面的子表达式零次或多次
  • +: 匹配前面的子表达式一次或多次
  • ?: 匹配前面的子表达式零次或一次
  • \d: 匹配一个数字字符,[0-9] 的缩写
  • \D 匹配任何非数字,[^0-9] 的缩写
  • \s 任何空格字符,[\t\n\x0B\f\r] 的缩写
  • \S 任何非空格字符,是 [^\s] 的缩写
  • \w: 匹配一个字母、数字或下划线字符
  • [abc]: 匹配方括号内的任意一个字符
  • ^: 匹配字符串的开始
  • $: 匹配字符串的结束

更多表达式,参考: regexr

Regex 类详解


Matcher

Matcher类实现 MatchResult 接口,它是一个正则表达式引擎,用于对字符序列执行匹配操作。主要包含以下方法:

  • boolean matches():测试正则表达式是否与模式匹配。
  • boolean find():找到与模式匹配的下一个表达式。
  • boolean find(int start):找到与给定起始编号中的模式匹配的下一个表达式。
  • String group():返回匹配的子序列。
  • int start():返回匹配子序列的起始索引。
  • int end():返回匹配子序列的结束索引。
  • int groupCount():返回匹配子序列的总数。

Pattern

Pattern类是正则表达式的编译版本,用于定义正则表达式引擎的模式。主要包含以下方法:

  • static Pattern compile(String regex):编译给定的正则表达式并返回 Pattern 的实例。
  • Matcher matcher(CharSequence input):创建一个匹配器,该匹配器将给定的输入与模式匹配。
  • static boolean matches(String regex, CharSequence input):它作为编译和匹配器方法的组合工作。它编译正则表达式并将给定的输入与模式匹配。
  • String[] split(CharSequence input):围绕给定模式的匹配项拆分给定的输入字符串。
  • String pattern():返回正则表达式模式。

PatternSyntaxException

PatternSyntaxException 类是抛出未经检查的异常,指示正则表达式模式中的语法错误。主要包含以下方法:

  • int getIndex():检索异常的索引
  • String getDescription():检索异常的描述信息
  • String getPattern():检索错误的正则表达式模式

MatchResult

MatchResult接口主要用于匹配操作的结果。此接口包含用于确定与正则表达式匹配的结果的查询方法。匹配边界、组和组边界可以通过。主要包含以下方法:

  • int start():返回匹配的开始索引
  • int start(int group):返回本次匹配期间给定组捕获的子序列的起始索引。
  • int end():返回最后一个匹配字符后的偏移量。
  • int end(int group):返回本次匹配期间给定组捕获的子序列的最后一个字符后的偏移量。
  • String group():返回与上一个匹配项匹配的输入子序列。
  • String group(int group):返回上一次匹配操作期间给定组捕获的输入子序列。
  • int groupCount():返回此匹配结果模式中的捕获组的数量。

正则使用场景


正则使用场景主要包含以下类型:

  • 输入验证,比如邮箱验证,手机号验证,URL 验证,密码强度验证
  • 文本搜索和替换,比如查找特定模式,替换特定模式
  • 文本拆分,比如按照空白字符拆分字符串
  • 日志和数据解析,比如提取IP地址,提取日期和时间
  • 数据清洗,比如删除HTML标签,格式化字符串
  • 编译器和解释器,比如识别标识符、关键字、操作符等
  • 数据库查询,比如使用 SQL 的 REGEXP 运算符进行复杂的模式匹配查询。
  • 文件名匹配,比如查找所有以 .txt 结尾的文件

除了上面的场景,正则表达式还可以使用到其他的场景,需要根据具体的场景而定。

示例演示


邮箱验证

验证邮箱地址是一个常见的正则表达式应用场景。首先,我们需要一个能够验证邮箱地址的正则表达式。一个常见的用于验证邮箱的正则表达式如下:

^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$

该正则表达式的解释如下:

  • ^:匹配字符串的开始。
  • [a-zA-Z0-9._%+-]+:匹配一个或多个字母、数字、点、下划线、百分号、加号或减号。
  • @:匹配@符号。
  • [a-zA-Z0-9.-]+:匹配一个或多个字母、数字、点或减号。
  • \.:匹配一个点。
  • [a-zA-Z]{2,}:匹配两个或更多的字母。
  • $:匹配字符串的结束。

下面是一个完整的 Java示例代码:

import java.util.regex.*;
public class EmailValidator {
    public static void main(String[] args) {
        String emailPattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$";
        String[] emails = {
            "valid.email@example.com",
            "invalid-email@example",
            "another.valid.email@example.co.uk",
            "invalid.email@.com",
            "valid_email123@example.org"
        };
        
        Pattern pattern = Pattern.compile(emailPattern);
        for (String email : emails) {
            Matcher matcher = pattern.matcher(email);
            boolean isMatch = matcher.matches();
            System.out.println("Email: " + email + " is valid? " + isMatch);
        }
    }
}

运行结果:

Email: valid.email@example.com is valid? true
Email: invalid-email@example is valid? false
Email: another.valid.email@example.co.uk is valid? true
Email: invalid.email@.com is valid? false
Email: valid_email123@example.org is valid? true

在上述代码中:

  • Pattern.compile(emailPattern):编译正则表达式。
  • pattern.matcher(email):创建一个匹配器对象,用于匹配给定的邮箱字符串。
  • matcher.matches():检查整个字符串是否与正则表达式匹配。

拆分字符串

在下面的示例中,正则表达式\s+表示一个或多个空白字符。split方法用于将字符串按匹配的模式拆分为多个部分。

import java.util.regex.*;

public class RegexExample {
    public static void main(String[] args) {
        String pattern = "\\s+";
        String text = "Split this string by spaces.";
        
        Pattern compiledPattern = Pattern.compile(pattern);
        String[] parts = compiledPattern.split(text);
        
        for (String part : parts) {
            System.out.println(part);
        }
    }
}

查找子字符串

在下面示例中,正则表达式\d+表示一个或多个数字字符。find方法用于查找所有匹配的子字符串。

import java.util.regex.*;

public class RegexExample {
    public static void main(String[] args) {
        String pattern = "\\d+";
        String text = "There are 123 apples and 456 oranges.";
        
        Pattern compiledPattern = Pattern.compile(pattern);
        Matcher matcher = compiledPattern.matcher(text);
        
        while (matcher.find()) {
            System.out.println("Found a number: " + matcher.group());
        }
    }
}

总结


正则表达式是一种功能强大且灵活的工具,能够极大地提高字符串处理的效率和精度。正则表达式的技术难度不大,但是很难记忆,而且在输入验证、文本搜索和替换、文本拆分、日志和数据解析、数据清洗、编译器和解释器等应用场景使用比较多。所以,掌握正则表达式还是有很大帮助。