ZetCode

Java MatchResult.end 方法

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

MatchResult.end 方法是 Java 正则表达式 API 的一部分。它返回匹配或捕获组的最后一个字符之后的偏移量。此方法对于确定输入字符串中的匹配位置非常有用。

MatchResult 是由 Matcher 实现的接口。end 方法提供有关匹配边界的信息。它有助于涉及正则表达式匹配的字符串操作任务。

MatchResult 接口概述

MatchResult 接口表示匹配操作的结果。它提供了查询匹配位置和组内容的方法。通常通过 Matcher 实例访问该接口。

关键方法包括 startendgroup。这些方法允许您检查匹配细节。MatchResult 常用在正则表达式处理流程中。

基本 end 方法用法

end 的最简单形式返回整个匹配的最后一个字符之后的偏移量。这对于字符串切片操作很有用。如果未尝试匹配,则该方法抛出 IllegalStateException

BasicEndExample.java
package com.zetcode;

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

public class BasicEndExample {

    public static void main(String[] args) {
        
        String input = "The quick brown fox jumps over the lazy dog";
        Pattern pattern = Pattern.compile("fox");
        Matcher matcher = pattern.matcher(input);
        
        if (matcher.find()) {
            int endPosition = matcher.end();
            System.out.println("Match ends at position: " + endPosition);
            System.out.println("Matched text: '" + 
                input.substring(matcher.start(), endPosition) + "'");
        }
    }
}

此示例在句子中查找单词 "fox"。end 方法返回 "fox" 中 'x' 之后的位置。我们将其与 start 一起使用以提取匹配的子字符串。

输出显示了结束位置和匹配的文本。请记住,在 Java 中,字符串位置从零开始。在子字符串操作中,结束位置是独占的。

带有捕获组的 end()

end(int group) 重载返回特定捕获组的结束位置。组 0 表示整个匹配,而组 1+ 对应于带括号的子模式。这有助于分析复杂的匹配。

GroupEndExample.java
package com.zetcode;

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

public class GroupEndExample {

    public static void main(String[] args) {
        
        String input = "Date: 2023-04-20, Time: 15:30";
        Pattern pattern = Pattern.compile(
            "(\\d{4})-(\\d{2})-(\\d{2})");
        Matcher matcher = pattern.matcher(input);
        
        if (matcher.find()) {
            System.out.println("Full match ends at: " + matcher.end());
            System.out.println("Year group ends at: " + matcher.end(1));
            System.out.println("Month group ends at: " + matcher.end(2));
            System.out.println("Day group ends at: " + matcher.end(3));
        }
    }
}

此示例从字符串中提取日期组件。我们在单独的组中捕获年、月和日。end(int) 方法显示每个组的结束位置。

输出演示了组位置如何与完整匹配相关。组号对应于其开括号的顺序。无效的组号抛出 IndexOutOfBoundsException

带有命名捕获组的 end

Java 7+ 支持在正则表达式模式中使用命名捕获组。end 方法使用其名称处理这些组。这使得代码比数字组索引更具可读性。

NamedGroupEndExample.java
package com.zetcode;

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

public class NamedGroupEndExample {

    public static void main(String[] args) {
        
        String input = "Product: Laptop, Price: $999.99";
        Pattern pattern = Pattern.compile(
            "Product: (?<product>\\w+), Price: \\$(?<price>\\d+\\.\\d{2})");
        Matcher matcher = pattern.matcher(input);
        
        if (matcher.find()) {
            System.out.println("Product ends at: " + 
                matcher.end("product"));
            System.out.println("Price ends at: " + 
                matcher.end("price"));
        }
    }
}

此示例使用命名组来提取产品信息。end(String) 方法返回命名组的位置。语法 (?<name>...) 定义了命名捕获组。

命名组提高了代码的可维护性。该方法为无效的组名抛出 IllegalArgumentException。支持混合使用命名组和编号组。

处理未匹配的情况

如果未找到或未尝试匹配,则 end 方法抛出 IllegalStateException。在调用 end 之前,始终检查 findmatches 的结果。

NoMatchExample.java
package com.zetcode;

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

public class NoMatchExample {

    public static void main(String[] args) {
        
        String input = "No numbers here";
        Pattern pattern = Pattern.compile("\\d+");
        Matcher matcher = pattern.matcher(input);
        
        try {
            // Wrong: calling end() without checking find()
            System.out.println("End position: " + matcher.end());
        } catch (IllegalStateException e) {
            System.out.println("Error: " + e.getMessage());
        }
        
        // Correct approach
        if (matcher.find()) {
            System.out.println("End position: " + matcher.end());
        } else {
            System.out.println("No match found");
        }
    }
}

此示例演示了对 end 的正确错误处理。第一次尝试在未检查匹配的情况下调用 end。第二种方法首先正确验证匹配。

始终遵循以下模式:调用 find,检查其返回值,然后使用 end。这可以防止代码中的运行时异常。

使用 end 的多个匹配项

当处理字符串中的多个匹配项时,end 会更新以反映每个匹配项的位置。这使得可以迭代处理输入中的所有匹配项。

MultipleMatchesExample.java
package com.zetcode;

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

public class MultipleMatchesExample {

    public static void main(String[] args) {
        
        String input = "cat, dog, fish, bird";
        Pattern pattern = Pattern.compile("\\b\\w{3}\\b");
        Matcher matcher = pattern.matcher(input);
        
        while (matcher.find()) {
            System.out.printf("Found '%s' at [%d-%d)%n",
                matcher.group(),
                matcher.start(),
                matcher.end());
        }
    }
}

此示例查找字符串中所有 3 个字母的单词。while 循环遍历每个匹配项。对于每个匹配项,我们使用 startend 打印匹配的文本及其位置范围。

输出显示了 end 如何随着每个匹配项而变化。该范围表示为 [start, end),遵循 Java 子字符串操作的标准。

带有 Region 方法的 end()

当使用 region 方法将匹配限制为输入的一部分时,end 仍然返回绝对位置。这些位置相对于完整的输入字符串,而不是该区域。

RegionEndExample.java
package com.zetcode;

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

public class RegionEndExample {

    public static void main(String[] args) {
        
        String input = "First: 123, Second: 456, Third: 789";
        Pattern pattern = Pattern.compile("\\d+");
        Matcher matcher = pattern.matcher(input);
        
        // Set region to only search after "First:"
        matcher.region(7, input.length());
        
        while (matcher.find()) {
            System.out.printf("Found '%s' at [%d-%d)%n",
                matcher.group(),
                matcher.start(),
                matcher.end());
        }
    }
}

此示例设置了从字符串中 "First:" 之后开始的区域。尽管有区域限制,但 end 仍返回相对于完整字符串的位置。这与其他的字符串操作保持一致。

输出显示了 "First:" 之后找到的数字。这些位置反映了它们在输入字符串中的绝对位置。区域边界仅影响匹配的开始位置,而不是位置报告。

来源

Java MatchResult 文档

本教程涵盖了 Java 中的 MatchResult.end 方法。我们通过实际示例探索了它的各种形式和用法场景。该方法对于使用正则表达式进行精确的字符串操作至关重要。

作者

我的名字是 Jan Bodnar,我是一位经验丰富的程序员,在该领域拥有多年的经验。我于 2007 年开始撰写编程文章,此后撰写了 1,400 多篇文章和八本电子书。凭借超过八年的教学经验,我致力于分享我的知识并帮助他人掌握编程概念。

列出所有Java教程