Java 正则表达式简介
Java 提供了 java.util.regex
包用于与正则表达式进行模式匹配。Java 正则表达式与 Perl 编程语言非常相似,易于学习。
正则表达式是一种特殊字符序列,帮助你在模式中匹配或查找其他字符串或字符串集合。它们可以用来搜索、编辑或操纵文本和数据。
Java 正则表达式类
java.util.regex
包主要包含以下三个类:
-
Pattern 类 - 一个 Pattern 对象是一个正则表达式的编译表示。Pattern 类没有提供公共构造函数。要创建一个模式,必须首先调用其中一个公共静态 compile() 方法,这些方法接受一个正则表达式作为第一个参数。
-
Matcher 类 - 一个 Matcher 对象是解释模式并执行输入字符串匹配操作的引擎。与 Pattern 类一样,Matcher 也没有提供公共构造函数。你可以通过调用 Pattern 对象的 matcher() 方法来获取一个 Matcher 对象。
-
PatternSyntaxException - 一个 PatternSyntaxException 对象是一个未检查的异常,表明正则表达式模式中存在语法错误。
正则表达式中的捕获组
捕获组是将多个字符视为单个单元的方式。它们是通过将要组合的字符放置在一对括号内创建的。例如,正则表达式 (dog)
创建了一个包含字母 "d", "o", 和 "g" 的单一组。
捕获组通过计算从左到右的开括号数量来进行编号。例如,在表达式 ((A)(B(C)))
中,有四个这样的组:
要找出表达式中有多少个组,可以在一个匹配器对象上调用 groupCount
方法。groupCount
方法返回一个整数,显示匹配器模式中存在的捕获组数量。
还有一个特殊的组,组 0,它总是代表整个表达式。这个组不包括在 groupCount
报告的总数中。
示例
以下示例说明了如何从给定的字母数字字符串中查找数字字符串:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches {
public static void main( String args[] ) {
String line = "This order was placed for QT3000! OK?";
String pattern = "(.*)(\\d+)(.*)";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(line);
if (m.find( )) {
System.out.println("Found value: " + m.group(0) );
System.out.println("Found value: " + m.group(1) );
System.out.println("Found value: " + m.group(2) );
} else {
System.out.println("NO MATCH");
}
}
}
输出
Found value: This order was placed for QT3000! OK?
Found value: This order was placed for QT300
Found value: 0
正则表达式语法
下面是 Java 中可用的所有正则表达式元字符语法列表:
子表达式 |
匹配项 |
^ |
匹配行首 |
$ |
匹配行尾 |
. |
匹配除换行符外的任意单个字符。使用 m 选项允许匹配换行符。 |
[...] |
匹配括号内的任意单个字符。 |
[^...] |
匹配括号外的任意单个字符。 |
\A |
字符串的开头。 |
\z |
字符串的结尾。 |
\Z |
字符串的结尾,除了允许的最终行终止符。 |
re* |
匹配前面表达式的 0 次或多次出现。 |
re+ |
匹配前面表达式的 1 次或多次出现。 |
re? |
匹配前面表达式的 0 次或 1 次出现。 |
re{n} |
匹配前面表达式的恰好 n 次出现。 |
re{n,} |
匹配前面表达式的至少 n 次出现。 |
re{n, m} |
匹配前面表达式的至少 n 次且至多 m 次出现。 |
a |
b |
(re) |
组合正则表达式并记住匹配的文本。 |
(? :re) |
组合正则表达式但不记住匹配的文本。 |
(?> re) |
匹配独立模式而不回溯。 |
\w |
匹配单词字符。 |
\W |
匹配非单词字符。 |
\s |
匹配空白符。相当于 [\t\n\r\f]。 |
\S |
匹配非空白符。 |
\d |
匹配数字。相当于 [0-9]。 |
\D |
匹配非数字。 |
\A |
匹配字符串的开头。 |
\Z |
匹配字符串的结尾。如果存在换行符,它匹配刚好在换行符前的位置。 |
\z |
匹配字符串的结尾。 |
\G |
匹配上次匹配结束的地方。 |
\n |
捕获组编号 "n" 的反向引用。 |
\b |
当在括号之外时,匹配单词边界;当在括号之内时,匹配退格符 (0x08)。 |
\B |
匹配非单词边界。 |
\n, \t, 等 |
匹配换行符、回车符、制表符等。 |
\Q |
从 \E 开始转义(引用)所有字符。 |
\E |
结束由 \Q 开始的转义。 |
正则表达式 - Matcher 类方法
以下是一些有用的实例方法列表:
索引方法
索引方法提供了有用的索引值,显示精确在哪里发现了匹配:
序号 |
方法 & 描述 |
1 |
public int start() 返回前一次匹配的起始索引。 |
2 |
public int start(int group) 返回前一次匹配过程中由指定组捕获的子序列的起始索引。 |
3 |
public int end() 返回匹配的最后一个字符之后的偏移量。 |
4 |
public int end(int group) 返回前一次匹配过程中由指定组捕获的子序列的最后一个字符之后的偏移量。 |
研究方法
研究方法回顾输入字符串并返回一个布尔值指示是否找到了模式:
序号 |
方法 & 描述 |
1 |
public boolean lookingAt() 尝试从区域的开始处匹配输入序列与模式。 |
2 |
public boolean find() 尝试查找输入序列中下一个匹配模式的子序列。 |
3 |
public boolean find(int start) 重置此匹配器,然后尝试从指定索引开始查找输入序列中下一个匹配模式的子序列。 |
4 |
public boolean matches() 尝试将整个区域与模式匹配。 |
Java 中的正则表达式替换方法
替换方法
替换方法对于替换输入字符串中的文本非常有用:
序号 |
方法 & 描述 |
1 |
public Matcher appendReplacement(StringBuffer sb, String replacement) 实现非终结的追加和替换步骤。 |
2 |
public StringBuffer appendTail(StringBuffer sb) 实现终结的追加和替换步骤。 |
3 |
public String replaceAll(String replacement) 用给定的替换字符串替换输入序列中每一个与模式匹配的子序列。 |
4 |
public String replaceFirst(String replacement) 用给定的替换字符串替换输入序列中第一个与模式匹配的子序列。 |
5 |
public static String quoteReplacement(String s) 对于指定的字符串返回一个文字替换字符串。此方法产生的字符串将在 Matcher 类的 appendReplacement 方法中作为文字替换 s 使用。 |
start 和 end 方法
下面的例子统计了单词 "cat" 在输入字符串中出现的次数:
示例
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches {
private static final String REGEX = "\\bcat\\b";
private static final String INPUT = "cat cat cat cattie cat";
public static void main( String args[] ) {
Pattern p = Pattern.compile(REGEX);
Matcher m = p.matcher(INPUT);
int count = 0;
while(m.find()) {
count++;
System.out.println("Match number "+count);
System.out.println("start(): "+m.start());
System.out.println("end(): "+m.end());
}
}
}
输出
Match number 1
start(): 0
end(): 3
Match number 2
start(): 4
end(): 7
Match number 3
start(): 8
end(): 11
Match number 4
start(): 19
end(): 22
你可以看到这个例子使用了单词边界来确保字母 "c" "a" "t" 不仅仅是更长单词的一个子字符串。它还给出了一些有关输入字符串中匹配位置的有用信息。
start
方法返回前一次匹配过程中由指定组捕获的子序列的起始索引,而 end
方法返回匹配的最后一个字符的索引,再加上一。
matches 和 lookingAt 方法
matches
和 lookingAt
方法都尝试将输入序列与模式匹配。但是,区别在于 matches
要求整个输入序列都与模式匹配,而 lookingAt
不要求这样。
这两个方法总是在输入字符串的开始处开始。下面的例子解释了它们的功能:
示例
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches {
private static final String REGEX = "foo";
private static final String INPUT = "fooooooooooooooooo";
private static Pattern pattern;
private static Matcher matcher;
public static void main( String args[] ) {
pattern = Pattern.compile(REGEX);
matcher = pattern.matcher(INPUT);
System.out.println("Current REGEX is: "+REGEX);
System.out.println("Current INPUT is: "+INPUT);
System.out.println("lookingAt(): "+matcher.lookingAt());
System.out.println("matches(): "+matcher.matches());
}
}
输出
Current REGEX is: foo
Current INPUT is: fooooooooooooooooo
lookingAt(): true
matches(): false
replaceFirst 和 replaceAll 方法
replaceFirst
和 replaceAll
方法替换与给定正则表达式匹配的文本。正如它们的名字所表明的那样,replaceFirst
替换第一次出现,而 replaceAll
替换所有出现。
下面的例子解释了它们的功能:
示例
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches {
private static String REGEX = "dog";
private static String INPUT = "The dog says meow. All dogs say meow.";
private static String REPLACE = "cat";
public static void main(String[] args) {
Pattern p = Pattern.compile(REGEX);
Matcher m = p.matcher(INPUT);
INPUT = m.replaceAll(REPLACE);
System.out.println(INPUT);
}
}
输出
The cat says meow. All cats say meow.
appendReplacement 和 appendTail 方法
Matcher 类也提供了 appendReplacement
和 appendTail
方法来替换文本。
下面的例子解释了它们的功能:
示例
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches {
private static String REGEX = "a*b";
private static String INPUT = "aabfooaabfooabfoob";
private static String REPLACE = "-";
public static void main(String[] args) {
Pattern p = Pattern.compile(REGEX);
Matcher m = p.matcher(INPUT);
StringBuffer sb = new StringBuffer();
while(m.find()) {
m.appendReplacement(sb, REPLACE);
}
m.appendTail(sb);
System.out.println(sb.toString());
}
}
输出
-foo-foo-foo-
PatternSyntaxException 类方法
PatternSyntaxException
是一个未检查的异常,表明正则表达式模式中存在语法错误。PatternSyntaxException
类提供了以下方法来帮助你确定出错原因:
序号 |
方法 & 描述 |
1 |
public String getDescription() 获取错误描述。 |
2 |
public int getIndex() 获取错误索引。 |
3 |
public String getPattern() 获取错误的正则表达式模式。 |
4 |
public String getMessage() 返回一个包含语法错误描述及其索引、错误的正则表达式模式以及模式中错误索引的视觉指示的多行字符串。 |