Java Matcher.useAnchoringBounds 方法
上次修改时间:2025 年 4 月 20 日
Matcher.useAnchoringBounds 方法控制匹配器在执行正则表达式操作时是否使用定位边界。定位边界影响 ^ 和 $ 定位符相对于输入区域的行为。
启用定位边界(默认)时,^ 匹配输入区域的开头,$ 匹配结尾。禁用时,这些定位符仅匹配整个输入字符串的实际开头/结尾。
基本定义
Matcher:一个 Java 类,通过解释 Pattern 对字符序列执行匹配操作。它提供了查找、匹配和替换文本的方法。
定位边界:一个设置,用于确定 ^ 和 $ 是匹配输入区域的边界(true)还是仅匹配输入的绝对开头/结尾(false)。
输入区域:当前正在考虑用于匹配的输入字符串的部分,可以使用 region 方法设置。
默认定位边界行为
此示例演示了启用定位边界时的默认行为。 ^ 和 $ 定位符匹配输入区域的开头和结尾。
package com.zetcode;
import java.util.regex.*;
public class AnchoringBoundsDefault {
public static void main(String[] args) {
String input = "start middle end";
Pattern pattern = Pattern.compile("^middle$");
Matcher matcher = pattern.matcher(input);
// Set region to "middle"
matcher.region(6, 12);
// Default anchoring bounds is true
System.out.println("Default anchoring bounds: " + matcher.useAnchoringBounds(true));
System.out.println("Matches in region: " + matcher.find());
}
}
在此示例中,我们将区域设置为“middle”,并尝试匹配“^middle$”。使用默认的定位边界(true),匹配成功,因为 ^ 和 $ 匹配区域边界。输出显示默认设置和匹配都为 true。
禁用定位边界
此示例显示了禁用定位边界时会发生什么。 ^ 和 $ 定位符将仅匹配输入字符串的绝对开头/结尾。
package com.zetcode;
import java.util.regex.*;
public class AnchoringBoundsDisabled {
public static void main(String[] args) {
String input = "start middle end";
Pattern pattern = Pattern.compile("^middle$");
Matcher matcher = pattern.matcher(input);
// Set region to "middle"
matcher.region(6, 12);
// Disable anchoring bounds
matcher.useAnchoringBounds(false);
System.out.println("Anchoring bounds disabled: " + !matcher.useAnchoringBounds());
System.out.println("Matches in region: " + matcher.find());
}
}
禁用定位边界后,相同的模式“^middle$”无法匹配,因为 ^ 和 $ 不再遵循区域边界。输出显示匹配尝试失败,演示了不同的行为。
具有多个区域的定位边界
此示例演示了定位边界如何影响同一输入字符串的多个区域的匹配。
package com.zetcode;
import java.util.regex.*;
public class AnchoringBoundsMultiRegion {
public static void main(String[] args) {
String input = "first second third";
Pattern pattern = Pattern.compile("^\\w+$");
Matcher matcher = pattern.matcher(input);
// Test with anchoring bounds enabled (default)
System.out.println("With anchoring bounds:");
testRegions(matcher, true);
// Test with anchoring bounds disabled
System.out.println("\nWithout anchoring bounds:");
testRegions(matcher, false);
}
private static void testRegions(Matcher matcher, boolean enable) {
matcher.useAnchoringBounds(enable);
// Test three different regions
matcher.region(0, 5); // "first"
System.out.println("Region 1 match: " + matcher.find());
matcher.region(6, 12); // "second"
System.out.println("Region 2 match: " + matcher.find());
matcher.region(13, 18); // "third"
System.out.println("Region 3 match: " + matcher.find());
}
}
此示例针对输入字符串的三个不同区域测试模式“^\w+$”。启用定位边界后,所有区域都匹配,因为 ^ 和 $ 匹配区域边界。禁用定位边界后,不会发生匹配,因为该模式需要匹配输入的绝对开头/结尾。
与透明边界结合
此示例显示了定位边界如何与透明边界交互,透明边界会影响后行断言和先行断言。
package com.zetcode;
import java.util.regex.*;
public class AnchoringBoundsWithTransparent {
public static void main(String[] args) {
String input = "prefix123suffix";
Pattern pattern = Pattern.compile("(?<=prefix)\\d+(?=suffix)");
Matcher matcher = pattern.matcher(input);
// Set region to "123suffix"
matcher.region(6, 15);
// Case 1: Both bounds enabled
matcher.useAnchoringBounds(true);
matcher.useTransparentBounds(false);
System.out.println("Anchoring true, Transparent false: " + matcher.find());
// Case 2: Anchoring disabled, Transparent false
matcher.useAnchoringBounds(false);
matcher.useTransparentBounds(false);
System.out.println("Anchoring false, Transparent false: " + matcher.find());
// Case 3: Anchoring false, Transparent true
matcher.useAnchoringBounds(false);
matcher.useTransparentBounds(true);
System.out.println("Anchoring false, Transparent true: " + matcher.find());
}
}
此示例演示了定位边界和透明边界之间的交互。当透明边界为 false 时,后行断言 (?<=prefix) 失败,因为它无法看到区域外部。只有第三种情况成功,因为透明边界允许环视断言看到区域外部。
实际用例
此示例显示了一个实际用例,用于在搜索较大文本中的模式时禁用定位边界。
package com.zetcode;
import java.util.regex.*;
public class AnchoringBoundsPractical {
public static void main(String[] args) {
String text = "Error: Invalid input\nWarning: Low memory\nError: File not found";
Pattern errorPattern = Pattern.compile("^Error: .+$", Pattern.MULTILINE);
Matcher matcher = errorPattern.matcher(text);
// With default anchoring bounds (matches only first line)
System.out.println("With default anchoring bounds:");
while (matcher.find()) {
System.out.println("Found: " + matcher.group());
}
// With anchoring bounds disabled (matches all error lines)
matcher.useAnchoringBounds(false);
System.out.println("\nWith anchoring bounds disabled:");
matcher.reset();
while (matcher.find()) {
System.out.println("Found: " + matcher.group());
}
}
}
在这个实际示例中,我们搜索日志中的错误消息。使用默认定位边界,只有第一行匹配,因为 ^ 和 $ 匹配区域边界。禁用定位边界允许在与 MULTILINE 模式结合使用时匹配所有错误行。
性能影响
此示例演示了在处理具有许多区域的大型文本时,定位边界的潜在性能影响。
package com.zetcode;
import java.util.regex.*;
public class AnchoringBoundsPerformance {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
sb.append("word").append(i).append(" ");
}
String input = sb.toString();
Pattern pattern = Pattern.compile("^word\\d+$");
Matcher matcher = pattern.matcher(input);
// Test with anchoring bounds enabled
long start = System.nanoTime();
testWithAnchoring(matcher, true);
long duration1 = System.nanoTime() - start;
// Test with anchoring bounds disabled
start = System.nanoTime();
testWithAnchoring(matcher, false);
long duration2 = System.nanoTime() - start;
System.out.printf("With anchoring bounds: %,d ns%n", duration1);
System.out.printf("Without anchoring bounds: %,d ns%n", duration2);
}
private static void testWithAnchoring(Matcher matcher, boolean enable) {
matcher.useAnchoringBounds(enable);
matcher.reset();
int pos = 0;
while (pos < matcher.regionEnd()) {
int spacePos = matcher.regionEnd();
if (matcher.regionEnd() > pos) {
spacePos = matcher.regionEnd();
for (int i = pos; i < matcher.regionEnd(); i++) {
if (matcher.regionEnd() > i &&
matcher.input().charAt(i) == ' ') {
spacePos = i;
break;
}
}
}
matcher.region(pos, spacePos);
matcher.find();
pos = spacePos + 1;
}
}
}
此性能测试表明,在使用许多小区域时,禁用定位边界有时可以提高性能。 确切的差异取决于正则表达式的复杂性和输入大小,但对于性能至关重要的代码来说,值得考虑。
边缘情况行为
此示例探讨了定位边界行为可能出乎意料或特别重要的边缘情况。
package com.zetcode;
import java.util.regex.*;
public class AnchoringBoundsEdgeCases {
public static void main(String[] args) {
// Empty input with empty region
testCase("", 0, 0);
// Empty region in non-empty input
testCase("hello", 2, 2);
// Region at exact start
testCase("start end", 0, 5);
// Region at exact end
testCase("start end", 6, 9);
}
private static void testCase(String input, int regionStart, int regionEnd) {
Pattern pattern = Pattern.compile("^.*$");
Matcher matcher = pattern.matcher(input);
matcher.region(regionStart, regionEnd);
System.out.printf("\nInput: '%s', Region: [%d,%d)%n",
input, regionStart, regionEnd);
// With anchoring bounds
matcher.useAnchoringBounds(true);
System.out.println("Anchoring true: " + matcher.find());
// Without anchoring bounds
matcher.useAnchoringBounds(false);
System.out.println("Anchoring false: " + matcher.find());
}
}
此示例测试空输入和区域等边缘情况。结果表明,定位边界会影响空区域是否匹配“.*”等模式。理解这些边缘情况对于健壮的正则表达式处理非常重要。
来源
Java Matcher.useAnchoringBounds 文档
在本文中,我们深入探讨了 Matcher.useAnchoringBounds 方法。 了解定位边界对于精确控制正则表达式匹配行为至关重要,尤其是在处理输入区域时。
作者
列出所有Java教程。