简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
正则表达式为匹配特定模式的字符串提供了便利。正则表达式中也有很多值得注意的细节问题,本篇文章主要通过一些实例讲述一下正则中断言的使用方法,以便在开发过程中进行查阅。
正则中的断言有如下几种形式:
(?=pattern)
(?!pattern)
(?<=pattern)
(?<!pattern)
接下来通过实例一一演示其作用及使用方式:
1、(?=pattern)
// 演示代码
public class PatternAssertion {
public static void main(String[] args) {
String input = "Hello Bubble Bulk";
Matcher matcher = Pattern.compile("Bu(?=bb)").matcher(input);
while (matcher.find()) {
int begin = matcher.start();
int end = matcher.end();
System.out.println("matched string: " + input.substring(begin, end));
System.out.println("span: (" + begin + ", " + end + ")");
}
}
}
执行结果
matched string: Bu
span: (6, 8)
通过执行结果可以看出,"Bu(?=bb)" 这个正则只匹配到了 "Bubble" 中的 "Bu",并没有匹配到 "Bulk" 中的 "Bu" 。这是因为 "Bu(?=bb)" 中的 "(?=bb)" 限制了 "Bu" 后面的模式必须是 "bb" ,因此在整个字符串 "Hello Bubble Bulk" 中,只有 "Bubble" 里面的这个 "Bu" 才是满足条件的。
2、(?!pattern)
// 演示代码
public class PatternAssertion {
public static void main(String[] args) {
String input = "Hello Bubble Bulk";
Matcher matcher = Pattern.compile("Bu(?!bb)").matcher(input);
while (matcher.find()) {
int begin = matcher.start();
int end = matcher.end();
System.out.println("matched string: " + input.substring(begin, end));
System.out.println("span: (" + begin + ", " + end + ")");
}
}
}
执行结果
matched string: Bu
span: (13, 15)
通过执行结果可以看出,"Bu(?!bb)" 这个正则只匹配到了 "Bulk" 中的 "Bu",并没有匹配到 "Bubble" 中的 "Bu" 。这是因为 "Bu(?!bb)" 中的 "(?!bb)" 限制了 "Bu" 后面的模式不能是 "bb" ,因此在整个字符串 "Hello Bubble Bulk" 中,只有 "Bulk" 里面的这个 "Bu" 才是满足条件的。
3、(?<=pattern)
// 演示代码
public class PatternAssertion {
public static void main(String[] args) {
String input = "Hello Bubble Bulk";
Matcher matcher = Pattern.compile("(?<=o\\s)Bu").matcher(input);
while (matcher.find()) {
int begin = matcher.start();
int end = matcher.end();
System.out.println("matched string: " + input.substring(begin, end));
System.out.println("span: (" + begin + ", " + end + ")");
}
}
}
执行结果
matched string: Bu
span: (6, 8)
通过执行结果可以看出,"(?<=o\s)Bu" 这个正则只匹配到了 "Bubble" 中的 "Bu",并没有匹配到 "Bulk" 中的 "Bu" 。这是因为 "(?<=o\s)Bu" 中的 "(?<=o\s)" 限制了 "Bu" 前面的模式必须是 "o\s" ,因此在整个字符串 "Hello Bubble Bulk" 中,只有 "Bubble" 里面的这个 "Bu" 才是满足条件的。
4、(?<!pattern)
// 演示代码
public class PatternAssertion {
public static void main(String[] args) {
String input = "Hello Bubble Bulk";
Matcher matcher = Pattern.compile("(?<!o\\s)Bu").matcher(input);
while (matcher.find()) {
int begin = matcher.start();
int end = matcher.end();
System.out.println("matched string: " + input.substring(begin, end));
System.out.println("span: (" + begin + ", " + end + ")");
}
}
}
执行结果
matched string: Bu
span: (13, 15)
通过执行结果可以看出,"(?<!o\s)Bu" 这个正则只匹配到了 "Bulk" 中的 "Bu",并没有匹配到 "Bubble" 中的 "Bu" 。这是因为 "(?<!o\s)Bu" 中的 "(?<!o\s)" 限制了 "Bu" 前面的模式不能是 "o\s" ,因此在整个字符串 "Hello Bubble Bulk" 中,只有 "Bulk" 里面的这个 "Bu" 才是满足条件的。
不消耗字符
正则中的断言在参与匹配时是不消耗字符串中的字符的,断言只是起到一个限制的作用。下面举例说明:
public class PatternAssertion {
public static void main(String[] args) {
String input = "Hello Bubble Bulk";
Matcher matcher = Pattern.compile("Bu(?=l).").matcher(input);
while (matcher.find()) {
int begin = matcher.start();
int end = matcher.end();
System.out.println("matched string: " + input.substring(begin, end));
System.out.println("span: (" + begin + ", " + end + ")");
}
}
}
执行结果
matched string: Bul
span: (13, 16)
这里使用的带断言的正则是 "Bu(?=l)." ,为了便于理解,在分析这个正则的时候可以先把其中的断言部分去掉,这样正则就变成了 "Bu." 。这个正则对整个字符串 "Hello Bubble Bulk" 进行匹配时会匹配到 "Bub" 和 "Bul" 两处,然而正则 "Bu(?=l)." 中的断言要求 "Bu" 后面只能是 "l" ,因此最终只有 "Bul" 满足条件,而 "Bub" 是不满足条件的。