前言
本文所讲的是正则进阶知识,不对正则基础知识过多描述,代码采用java语言编写。
一个完整的正则表达式由两种字符构成:特殊字符(元字符)和普通字符,特殊字符是我们学习正则表达式中的通配符。
正则匹配三种模式
贪婪模式
在java中,模式默认为贪婪模式。
贪婪模式会尽可能多地匹配符合规则的字符。当采用贪婪模式时,正则表达式引擎将向前查找并匹配尽可能多的字符,直到找不到符合条件的字符为止。贪婪模式下的重复匹配操作符主要包括:
*
:匹配前一个字符或组零次或更多次。+
:匹配前一个字符或组一次或更多次。{m,n}
:匹配前一个字符或组最少 m 次,最多 n 次。
例如,对于字符串 "aabbcc" 和正则表达式 ab*c
,贪婪模式下,匹配结果为 "aabb"(匹配了两个 b),代码块如下:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class GroupExample {
public static void main(String[] args) {
Pattern pattern = Pattern.compile("ab.*c");
Matcher matcher = pattern.matcher("aabbcc");
if (matcher.find())
{
System.out.println(matcher.group());
}
}
}
输出将是:
abbcc
懒惰模式 (非贪婪模式)
在正则表达式语法中,问号(“?”)具有两种不同的含义,取决于它在正则表达式的什么位置。
当问号跟在重复限定符(如星号“”或加号“+”)的后面时,它会将匹配模式变为非贪婪,从而实现懒惰匹配。这意味着正则表达式引擎会尝试尽可能少的匹配字符,直到找到满足模式的最短字符串。
例如,正则表达式“a.?b”中的问号就是在星号后面使用的,它将星号的贪婪匹配模式变为非贪婪模式,从而实现了懒惰匹配。
另一方面,当问号不跟在重复限定符的后面时,它表示可选项,可以将前面的字符或组指定为可选的。这个问号通常称为零宽度断言(lookaround),因为它不匹配任何字符,而只是断言某些条件满足。
。
因此,问号在正则表达式中的含义取决于它的上下文和使用方式。加上问号可以实现懒惰匹配,但它也可以用于其他不同的目的。
举一个例子,对于字符串 "aabbcc" 和正则表达式 ab*c
,懒惰模式下,匹配结果为 "aabb"(匹配了两个 b),代码块如下:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class GroupExample {
public static void main(String[] args) {
Pattern pattern = Pattern.compile("ab.*?c");
Matcher matcher = pattern.matcher("aabbcc");
if (matcher.find())
{
System.out.println(matcher.group());
}
}
}
输出将是:
abbc
所以二者的区别在于:
贪婪模式:找出长度最大并且符合要求,尽可能多地去匹配。
懒惰模式:找出长度最小且符合要求的。
独占模式
*+:占有性限定符。它将匹配前一个字符或组零次或多次,但在匹配过程中,它不会回溯。
对于字符串 "aaab" 和正则表达式 a*+
,匹配到了3个 'a'。尽管占有性限定符不会回溯,但在这种情况下,结果与贪婪限定符相同。
总结
在正则表达式的三种模式(贪婪、非贪婪和占有性)中,贪婪模式和非贪婪模式会进行回溯(backtracking),而占有性模式不会回溯。
在实际使用中,选择合适的模式取决于您的需求和预期匹配结果。回溯可能会影响正则表达式性能,而占有性模式可以在某些情况下避免性能问题。然而,请注意,占有性模式可能使得正则表达式无法找到有效匹配。
group 函数的作用
在 Java 中,正则表达式通常与 Pattern
和 Matcher
类一起使用。
其中,Matcher
类提供了一个名为 group
的函数,用来获取匹配到的子串或者某个分组(group)的内容。
在正则表达式中,可以使用括号将一部分表达式括起来,从而创建一个分组。例如,正则表达式 (ab)+
匹配一个或多个由字符串 "ab" 组成的组合,其中括号中的 +
表示一个或多个,而加号前面的括号表示一个分组。
当使用 Matcher 类的 find()
方法或 matches()
方法进行正则表达式匹配时,如果匹配成功,可以使用 group()
方法获取匹配到的整个子串,或者使用 group(int groupNum)
方法获取某个特定分组的内容。
例如,以下代码演示了如何使用 Matcher
类的 group()
方法获取匹配到的子串和分组内容:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class GroupExample {
public static void main(String[] args) {
String input = "ababab";
String patternString = "(ab)+";
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
System.out.println("Matched string: " + matcher.group());
System.out.println("Group 1: " + matcher.group(1));
}
}
}
输出将是:
Matched string: ababab
Group 1: ab
环视(Lookaround)
环视分为四种,分别是顺序肯定环视,顺序否定环视,逆序肯定环视,逆序否定环视。
顺序环视 | 表达式 |
---|---|
顺序否定环视 | (?!expression) |
顺序肯定环视 | (?=expression) |
逆序否定环视 | (? |
逆序肯定环视 | (?
|