Java正则表达式完全指南:从基础到高级实例

Java中的正则表达式

欢迎来到Java中的正则表达式教程。在Java中,正则表达式也被称为Regex。当我刚开始编程时,Java正则表达式对我来说是一场噩梦。本教程旨在帮助您掌握Java中的正则表达式。我也会经常回到这里复习我的Java Regex知识。

在Java中,正则表达式定义了字符串的模式。正则表达式可用于搜索、编辑或操作文本。正则表达式并不特定于某种语言,但在每种语言中的实现略有不同。Java中的正则表达式与Perl的正则表达式最为相似。Java正则表达式相关的类位于java.util.regex包中,包含三个主要类。

Java正则表达式的三个核心类

  • Pattern:Pattern对象是正则表达式的编译表示形式。Pattern类没有任何公共构造函数,我们使用它的公共静态方法compile(),通过传递正则表达式作为参数来创建Pattern对象。
  • Matcher:Matcher是Java正则表达式引擎对象,用于将输入字符串与创建的模式对象进行匹配。Matcher类没有任何公共构造函数,我们使用模式对象的matcher()方法来获取Matcher对象,该方法以输入字符串作为参数。然后我们使用matches()方法,根据输入字符串是否与正则表达式模式匹配来返回布尔结果。
  • PatternSyntaxException:如果正则表达式语法不正确,将抛出PatternSyntaxException异常。

让我们来看一下Java正则表达式的示例程序。

package com.Olivia.util;

import java.util.regex.*;

public class PatternExample {

    public static void main(String[] args) {
        Pattern pattern = Pattern.compile(".xx.");
        Matcher matcher = pattern.matcher("MxxY");
        System.out.println("输入字符串是否匹配正则表达式 - "+matcher.matches());
        // 错误的正则表达式
        pattern = Pattern.compile("*xx*");

    }
}

当我们运行这个Java正则表达式示例程序时,会得到以下输出。

输入字符串是否匹配正则表达式 - true
Exception in thread "main" java.util.regex.PatternSyntaxException: Dangling meta character '*' near index 0
*xx*
^
    at java.util.regex.Pattern.error(Pattern.java:1924)
    at java.util.regex.Pattern.sequence(Pattern.java:2090)
    at java.util.regex.Pattern.expr(Pattern.java:1964)
    at java.util.regex.Pattern.compile(Pattern.java:1665)
    at java.util.regex.Pattern.(Pattern.java:1337)
    at java.util.regex.Pattern.compile(Pattern.java:1022)
    at com.Olivia.util.PatternExample.main(PatternExample.java:13)

由于Java正则表达式主要围绕字符串(String)展开,因此在Java 1.4中对String类进行了扩展,提供了一个名为matches()的方法来进行正则表达式模式匹配。该方法内部使用Pattern和Matcher这两个Java正则表达式类来处理,但显然它减少了代码行数。Pattern类也包含一个matches()方法,它接受正则表达式和输入字符串作为参数,并在匹配后返回布尔结果。因此,下面的代码在Java中使用正则表达式可以很好地工作。

String str = "bbb";
System.out.println("使用String的matches方法: "+str.matches(".bb"));
System.out.println("使用Pattern的matches方法: "+Pattern.matches(".bb", str));

如果您只需要检查输入字符串是否与模式匹配,可以通过使用简单的字符串matches()方法来节省时间和代码行数。只有在您需要操作输入字符串或需要重复使用模式时,才应该使用Pattern和Matcher类。请注意,正则表达式定义的模式从左到右应用于字符串,并且一旦源字符用于匹配,就无法重复使用。例如,正则表达式”121″将仅在”31212142121″中匹配两次,如”_121____121″。

Java中的正则表达式:常见匹配符号

正则表达式 描述 示例
. 匹配任意单个字符 (“…”, “a%”) – true
(“…”, “.a”) – true
(“…”, “a”) – false
^aaa 匹配行首的aaa正则表达式 (“^a.c.”, “abcd”) – true
(“^a”, “ac”) – false
aaa$ 匹配行尾的aaa正则表达式 (“…cd$”, “abcd”) – true
(“a$”, “a”) – true
(“a$”, “aca”) – false
[abc] 可以匹配字母a、b或c中的任意一个。[]被称为字符类。 (“^[abc]d.”, “ad9”) – true
(“[ab].d$”, “bad”) – true
(“[ab]x”, “cx”) – false
[abc][12] 可以匹配a、b或c后跟1或2 (“[ab][12].”, “a2#”) – true
(“[ab]…[12]”, “acd2”) – true
(“[ab][12]”, “c2”) – false
[^abc] 当^是[]中的第一个字符时,它表示否定模式,匹配除a、b或c之外的任何字符 (“[^ab][^12].”, “c3#”) – true
(“[^ab]…[^12]”, “xcd3”) – true
(“[^ab][^12]”, “c2”) – false
[a-e1-8] 匹配a到e或1到8之间的范围 (“[a-e1-3].”, “d#”) – true
(“[a-e1-3]”, “2”) – true
(“[a-e1-3]”, “f2”) – false
xx|yy 匹配正则表达式xx或yy (“xx|yy”, “xx”) – true
(“xx|yy”, “yy”) – true
(“xx|yy”, “xy”) – false

Java正则表达式元字符

在Java正则表达式中,我们有一些元字符,它们类似于常见匹配模式的简写代码。

正则表达式 描述
\d 任何数字,是[0-9]的简写
\D 任何非数字字符,是[^0-9]的简写
\s 任何空白字符,是[\t\n\x0B\f\r]的简写
\S 任何非空白字符,是[^\s]的简写
\w 任何单词字符,是[a-zA-Z_0-9]的简写
\W 任何非单词字符,是[^\w]的简写
\b 单词边界
\B 非单词边界

在正则表达式中,有两种方法可以将元字符用作普通字符。

  • 在元字符之前加上反斜杠(\)进行转义。
  • 将元字符保持在 \Q(引用开始)和 \E(引用结束)之间。

Java中的正则表达式 – 量词

这是文章《在Java中的正则表达式 – Java的正则表达式示例》的第2部分(共2部分)。

Java的正则表达式量词用于指定要匹配的字符出现的次数。

正则表达式 描述
x? x出现一次或完全不出现
X* X出现零次或多次
X+ X出现一次或多次
X{n} X恰好出现n次
X{n,} X出现至少n次
X{n,m} X出现至少n次但不超过m次

Java正则表达式量词可以与字符类和捕获组一起使用。例如,[abc]+表示a、b或c出现一次或多次。(abc)+表示组”abc”出现一次或多次。我们现在将讨论捕获组。

Java中的正则表达式 – 捕获组

在Java中,正则表达式的捕获组用于将多个字符视为单个单位。您可以使用()创建一个组。与捕获组匹配的输入字符串部分将保存到内存中,并可以使用反向引用进行调用。您可以使用matcher.groupCount方法来找出Java正则表达式模式中捕获组的数量。例如,((a)(bc))包含3个捕获组-((a)(bc)),(a)和(bc)。您可以在正则表达式中使用反向引用,使用反斜杠(\)和要调用的组的编号。捕获组和反向引用可能令人困惑,让我们通过一个例子来理解。

System.out.println(Pattern.matches("(\\w\\d)\\1", "a2a2")); //true
System.out.println(Pattern.matches("(\\w\\d)\\1", "a2b2")); //false
System.out.println(Pattern.matches("(AB)(B\\d)\\2\\1", "ABB2B2AB")); //true
System.out.println(Pattern.matches("(AB)(B\\d)\\2\\1", "ABB2B3AB")); //false

在第一个例子中,运行时第一个捕获组是(\w\d),当与输入字符串”a2a2″匹配并保存在内存中时,它的值为”a2″。因此,\1引用”a2″,并且返回true。由于同样的原因,第二个语句打印出false。请自行理解语句3和4的情况。现在我们来看一些Pattern类和Matcher类的重要方法。

  1. 我们可以使用标志位创建 Pattern 对象。例如,Pattern.CASE_INSENSITIVE 可以实现大小写不敏感的匹配。
  2. Pattern 类还提供了一个与 String 类 split() 方法类似的 split(String) 方法。
  3. Pattern 类的 toString() 方法返回编译此正则表达式的字符串。
  4. Matcher 类具有 start() 和 end() 索引方法,可以准确地显示匹配项在输入字符串中的位置。
  5. Matcher 类还提供了字符串处理方法 replaceAll(String replacement) 和 replaceFirst(String replacement)。

让我们在一个简单的示例程序中看看这些Java正则表达式方法。

package com.Olivia.util;

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

public class RegexExamples {

	public static void main(String[] args) {
		// 使用标志位创建pattern
		Pattern pattern = Pattern.compile("ab", Pattern.CASE_INSENSITIVE);
		Matcher matcher = pattern.matcher("ABcabdAb");
		// 使用Matcher的find(), group(), start()和end()方法
		while (matcher.find()) {
			System.out.println("找到文本 \"" + matcher.group()
					+ "\" 起始索引为 " + matcher.start()
					+ " 结束索引为 " + matcher.end());
		}

		// 使用Pattern的split()方法
		pattern = Pattern.compile("\\W");
		String[] words = pattern.split("one@two#three:four$five");
		for (String s : words) {
			System.out.println("使用Pattern.split()分割: " + s);
		}

		// 使用Matcher的replaceFirst()和replaceAll()方法
		pattern = Pattern.compile("1*2");
		matcher = pattern.matcher("11234512678");
		System.out.println("使用replaceAll: " + matcher.replaceAll("_"));
		System.out.println("使用replaceFirst: " + matcher.replaceFirst("_"));
	}

}

以上Java正则表达式示例程序的输出如下:

找到文本 "AB" 起始索引为 0 结束索引为 2
找到文本 "ab" 起始索引为 3 结束索引为 5
找到文本 "Ab" 起始索引为 6 结束索引为 8
使用Pattern.split()分割: one
使用Pattern.split()分割: two
使用Pattern.split()分割: three
使用Pattern.split()分割: four
使用Pattern.split()分割: five
使用replaceAll: _345_678
使用replaceFirst: _34512678

关于Java中的正则表达式就介绍到这里。Java的正则表达式一开始看起来可能很难,但如果您在实际中使用一段时间,就会发现学习和使用它们变得很容易。

您可以从我们的GitHub存储库中查找完整的代码和更多的正则表达式示例。

bannerAds