ZetCode

Java Matcher.hasAnchoringBounds 方法

上次修改时间:2025 年 4 月 20 日

Java 正则表达式包中的 Matcher.hasAnchoringBounds 方法检查匹配器是否正在使用锚定边界。锚定边界会影响 ^$ 元字符在匹配时的行为。

当启用锚定边界(默认)时,^$ 将在输入文本区域的开头和结尾进行匹配。当禁用时,它们仅在输入的实际开始/结束处匹配,忽略区域边界。

Matcher.hasAnchoringBounds 概述

hasAnchoringBounds 方法返回一个布尔值,指示是否启用了锚定边界。此设置由 useAnchoringBounds 方法控制。默认情况下,锚定边界已启用。

当处理输入文本的子区域时,锚定边界尤其重要。它们决定了模式锚点是否应该尊重当前的区域边界或完整的输入边界。

基本 hasAnchoringBounds 示例

此示例演示了锚定边界的默认行为以及如何使用 hasAnchoringBounds 检查其状态。我们将创建一个简单的匹配器并检查其锚定边界设置。

HasAnchoringBoundsBasic.java
package com.zetcode;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class HasAnchoringBoundsBasic {

    public static void main(String[] args) {
        
        String input = "start middle end";
        String regex = "^middle$";
        
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);
        
        // Check default anchoring bounds status
        boolean hasBounds = matcher.hasAnchoringBounds();
        System.out.println("Default hasAnchoringBounds: " + hasBounds);
        
        // Try to match with default bounds
        boolean matches = matcher.find();
        System.out.println("Matches with default bounds: " + matches);
    }
}

在此示例中,我们使用默认的锚定边界设置创建了一个匹配器。hasAnchoringBounds 方法返回 true,表明锚定边界已启用。该模式匹配失败,因为 ^$ 遵循完整的输入边界。

禁用锚定边界

此示例展示了如何使用 useAnchoringBounds(false) 禁用锚定边界,并使用 hasAnchoringBounds 验证更改。我们将看到这如何影响模式匹配。

DisableAnchoringBounds.java
package com.zetcode;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class DisableAnchoringBounds {

    public static void main(String[] args) {
        
        String input = "start middle end";
        String regex = "^middle$";
        
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);
        
        // Disable anchoring bounds
        matcher.useAnchoringBounds(false);
        System.out.println("After disabling: " + 
            matcher.hasAnchoringBounds());
            
        // Try to match with disabled bounds
        boolean matches = matcher.find();
        System.out.println("Matches with disabled bounds: " + matches);
    }
}

调用 useAnchoringBounds(false) 后,hasAnchoringBounds 方法返回 false。该模式仍然不匹配,因为我们正在搜索整个输入。锚点现在引用完整的输入边界。

带有区域的锚定边界

此示例演示了锚定边界如何与区域设置交互。我们将设置输入的子区域,并观察锚定边界如何影响匹配。

AnchoringBoundsWithRegion.java
package com.zetcode;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AnchoringBoundsWithRegion {

    public static void main(String[] args) {
        
        String input = "start middle end";
        String regex = "^middle$";
        
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);
        
        // Set region to "middle"
        matcher.region(6, 12);
        
        // With anchoring bounds (default)
        boolean matchesWithBounds = matcher.find();
        System.out.println("With anchoring bounds: " + matchesWithBounds);
        
        // Without anchoring bounds
        matcher.useAnchoringBounds(false);
        boolean matchesWithoutBounds = matcher.find();
        System.out.println("Without anchoring bounds: " + matchesWithoutBounds);
    }
}

启用锚定边界(默认)时,^$ 在区域边界处匹配,因此该模式匹配。禁用时,锚点引用完整的输入边界,导致匹配失败。

带有多行输入的锚定边界

此示例探讨了锚定边界如何与多行输入和 MULTILINE 标志交互。我们将看到不同的组合如何影响匹配。

AnchoringBoundsMultiline.java
package com.zetcode;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AnchoringBoundsMultiline {

    public static void main(String[] args) {
        
        String input = "first line\nsecond line\nthird line";
        String regex = "^second$";
        
        // With MULTILINE flag
        Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
        Matcher matcher = pattern.matcher(input);
        
        System.out.println("With MULTILINE and anchoring bounds:");
        System.out.println("hasAnchoringBounds: " + 
            matcher.hasAnchoringBounds());
        while (matcher.find()) {
            System.out.println("Found at: " + matcher.start());
        }
        
        // Without MULTILINE flag
        matcher = Pattern.compile(regex).matcher(input);
        matcher.useAnchoringBounds(false);
        System.out.println("\nWithout MULTILINE, no anchoring bounds:");
        while (matcher.find()) {
            System.out.println("Found at: " + matcher.start());
        }
    }
}

使用 MULTILINE 标志时,^ 在行终止符之后匹配,而与锚定边界无关。没有 MULTILINE 且禁用锚定边界时,^ 仅在输入的绝对开头匹配。

锚定边界对性能的影响

此示例检查锚定边界是否影响匹配性能。我们将比较启用和禁用锚定边界时的匹配时间。

AnchoringBoundsPerformance.java
package com.zetcode;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AnchoringBoundsPerformance {

    public static void main(String[] args) {
        
        String input = "sample text ".repeat(100000) + "target";
        String regex = "^target$";
        
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);
        
        // With anchoring bounds (default)
        long startTime = System.nanoTime();
        boolean found = matcher.find();
        long duration = System.nanoTime() - startTime;
        System.out.printf("With anchoring bounds: %d ns, found: %b%n",
            duration, found);
            
        // Without anchoring bounds
        matcher.useAnchoringBounds(false);
        startTime = System.nanoTime();
        found = matcher.find();
        duration = System.nanoTime() - startTime;
        System.out.printf("Without anchoring bounds: %d ns, found: %b%n",
            duration, found);
    }
}

锚定边界对性能的影响通常可以忽略不计。这两个版本都以相似的时间完成,因为正则表达式引擎优化了锚点匹配。主要区别在于匹配行为,而不是性能。

带有重置的锚定边界

此示例展示了 reset 方法如何影响锚定边界设置。我们将验证重置匹配器后边界设置是否保留。

AnchoringBoundsReset.java
package com.zetcode;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AnchoringBoundsReset {

    public static void main(String[] args) {
        
        String input = "test string";
        Pattern pattern = Pattern.compile("^test");
        Matcher matcher = pattern.matcher(input);
        
        // Change anchoring bounds
        matcher.useAnchoringBounds(false);
        System.out.println("Before reset: " + 
            matcher.hasAnchoringBounds());
            
        // Reset matcher
        matcher.reset();
        System.out.println("After reset: " + 
            matcher.hasAnchoringBounds());
            
        // Reset with new input
        matcher.reset("new input");
        System.out.println("After reset with new input: " + 
            matcher.hasAnchoringBounds());
    }
}

reset 方法保留锚定边界设置,无论是否使用新的输入字符串调用。这表明边界设置是匹配器的属性,而不是其当前状态的属性。

来源

Java Matcher.hasAnchoringBounds 文档

在本文中,我们探讨了 Matcher.hasAnchoringBounds 方法及其对 Java 中正则表达式匹配的影响。在使用输入区域或多行文本时,理解锚定边界至关重要。

作者

我叫 Jan Bodnar,是一名敬业的程序员,在这一领域拥有多年的经验。我从 2007 年开始撰写编程文章,至今已撰写了 1,400 多篇文章和 8 本电子书。凭借超过八年的教学经验,我致力于分享我的知识,并帮助他人掌握编程概念。

列出所有Java教程