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类的重要方法。
- 我们可以使用标志位创建 Pattern 对象。例如,Pattern.CASE_INSENSITIVE 可以实现大小写不敏感的匹配。
- Pattern 类还提供了一个与 String 类 split() 方法类似的 split(String) 方法。
- Pattern 类的 toString() 方法返回编译此正则表达式的字符串。
- Matcher 类具有 start() 和 end() 索引方法,可以准确地显示匹配项在输入字符串中的位置。
- 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存储库中查找完整的代码和更多的正则表达式示例。