正则表达式中,有些结构不是真正匹配文本, 而只负责判断在某个位置左/右侧的文本是否符合要求。断言常见有单词边界、行起始/结束位置和环视。本文主要介绍前两种断言。
单词边界是用于确定单词的边界位置, 记作: \b
。
单词边界有两个特点:
单词边界并不区分左右。在单词边界只有左侧是单词字符, 也可能只有右侧是单词字符, 总的来说, 单词字符只能出现在一侧。
单词字符要求 另一边不是单词字符。一边必须出现单词字符, 另一边可以出现非单词字符, 也可能没有字符。
// Java 实现
String regex2 = "\\b\\w+\\b";
String str = "a sentence\tcontains\na alot of words.end";
Pattern compile1 = Pattern.compile(regex2);
Matcher matcher1 = compile1.matcher(str);
while (matcher1.find()) {
System.out.print(matcher1.group() + "");
}
// 输出结果
//a sentence contains a alot of words end
在正则中用于匹配某个位置而不是文本, 这类匹配位置的元素叫作 锚点。上一点说到单词边界就是锚点, 常见的锚点还有 ^
和 $。^
会把整个表达式的匹配定位到字符串开始的位置。某些情况下可以匹配字符串内部的行起始位置, 常用的方法就是在正则表达式之前加上 (?m)
(表示采用多行模式), 记作 (?m)^
。
// Java 代码
String beginWord = "first line\nsecondf\nlast line";
Pattern compile2 = Pattern.compile("^\\w+");
Matcher matcher2 = compile2.matcher(beginWord);
while (matcher2.find()) {
System.out.print(matcher2.group() + " ");
}
System.out.println();
// 输出结果
//first
Pattern compile3 = Pattern.compile("(?m)^\\w+");
Matcher matcher3 = compile3.matcher(beginWord);
while (matcher3.find()) {
System.out.print(matcher3.group() + " ");
}
// 输出结果
//first secondf last
如果只关心整个字符串的起始位置则使用 \A
, 在任何情况下(包括多行模式)都只【匹配整个字符串的起始位置。
// Java
Pattern compile4 = Pattern.compile("(?m)\\A\\w+");
Matcher matcher4 = compile4.matcher(beginWord);
while (matcher4.find()) {
System.out.print(matcher4.group() + " ");
}
// 输出结果
//first
常见的行结束符为 $ , 它匹配整个字符串的结束位置, 如果是行终止符则行匹配终止符之前的位置, 否则匹配最后一个字符串之后的位置。比如: abcd 匹配的是d之后的位置, abcd[NL] 匹配的是[NL]之前的位置。这里用[NL]表示换行符,不同操作系统的换行符不相同, 具体区别如下:
系统 | 行终止符号 |
---|---|
UNIX/Linux | \n |
Windows | \r\n |
MacOS | \n (OSX 9 之前的版本为 \r) |
// Java
Pattern compile5 = Pattern.compile("\\w+$");
Matcher matcher5 = compile5.matcher(beginWord);
while (matcher5.find()) {
System.out.print(matcher5.group() + " ");
}
// 输出结果
//line
System.out.println();
Pattern compile6 = Pattern.compile("(?m)\\w+$");
Matcher matcher6 = compile6.matcher(beginWord);
while (matcher6.find()) {
System.out.print(matcher6.group() + " ");
}
// 输出结果
//line secondf line
与 $ 类似的还有两个标记 \Z
和 \z
, 他们不受多行模式的影响, 在任何情况下都可以匹配字符串的结束位置。\Z
等价于 非多行模式下的 $, \z
则匹配真个字符串的结束位置, 包括终止符。
为了验证整个字符串是否由 pattern 匹配, 常用的做法是在 pattern 的两端添加 ^
和 $。
// Java
System.out.println(Pattern.compile("1\\Z").matcher("1\n").find()); // true
System.out.println(Pattern.compile("1\\z").matcher("1").find()); // true
System.out.println(Pattern.compile("1\\z").matcher("1\n").find()); // false
// Java 可以理解成默认在两端都添加了行起始和结束符号
System.out.println("123456".matches("\\d{6}")); // true
System.out.println("123456".matches("^\\d{6}$")); // true
注意: 在起始/结束位置进行替换, 只是在起始/结束位置添加一些字符, 位置本身仍然存在。