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教程。