ZetCode

Java MatchResult.start 方法

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

MatchResult.start 方法是 Java 正则表达式包的一部分。它返回匹配项或特定捕获组的起始索引。此方法对于确定输入字符串中匹配项的位置至关重要。

MatchResult 接口由 Matcher 实现。它提供了查询匹配结果的方法。start 方法有助于需要位置信息的文本处理任务。

MatchResult 接口概述

MatchResult 提供了访问匹配信息的方法。它包括获取匹配的起始和结束位置的方法。该接口还提供了对匹配文本和组信息的访问。

start 方法有两个变体:一个没有参数,用于整个匹配项;另一个带有组号参数。两者都返回输入字符串中匹配位置的从零开始的索引。

MatchResult.start 的基本用法

start 的最简单用法是找到完整匹配项的位置。此示例演示了查找字符串中单词的起始位置。该方法返回匹配开始的索引。

BasicStartExample.java
package com.zetcode;

import java.util.regex.*;

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

在此示例中,我们编译一个简单的模式来匹配单词 "fox"。找到匹配项后,我们使用 start 来获取其起始位置。输出显示了 "fox" 在输入字符串中开始的索引。

将 start 与捕获组一起使用

start(int group) 返回特定捕获组的起始位置。组从左到右编号,从 1 开始。组 0 始终指整个匹配项。

GroupStartExample.java
package com.zetcode;

import java.util.regex.*;

public class GroupStartExample {
    public static void main(String[] args) {
        String text = "Date: 2023-05-15, Time: 14:30";
        Pattern pattern = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})");
        Matcher matcher = pattern.matcher(text);
        
        if (matcher.find()) {
            System.out.println("Full match starts at: " + matcher.start());
            System.out.println("Year starts at: " + matcher.start(1));
            System.out.println("Month starts at: " + matcher.start(2));
            System.out.println("Day starts at: " + matcher.start(3));
        }
    }
}

此示例演示了查找日期不同部分的起始位置。该模式将年、月和日捕获为单独的组。我们使用 start(1)start(2)start(3) 来获取它们各自的位置。

使用 start 处理多个匹配项

在字符串中处理多个匹配项时,start 返回找到的每个匹配项的位置。此示例显示了如何遍历所有匹配项并记录它们的起始位置。

MultipleMatchesExample.java
package com.zetcode;

import java.util.regex.*;

public class MultipleMatchesExample {
    public static void main(String[] args) {
        String text = "cat, bat, rat, mat, hat";
        Pattern pattern = Pattern.compile("[a-z]at");
        Matcher matcher = pattern.matcher(text);
        
        while (matcher.find()) {
            System.out.println("Found '" + matcher.group() + 
                "' at position: " + matcher.start());
        }
    }
}

此代码查找以 "at" 结尾的所有三个字母的单词。对于 find 找到的每个匹配项,我们打印匹配的文本及其起始位置。start 方法为我们提供了每个匹配项的精确位置。

将 start() 与命名组一起使用

Java 正则表达式支持命名捕获组。start(String name) 变体允许您使用组名获取起始位置。在处理复杂模式时,这使代码更具可读性。

NamedGroupStartExample.java
package com.zetcode;

import java.util.regex.*;

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

此示例使用命名组来捕获产品和价格信息。我们没有使用数字组索引,而是使用了描述性名称。start(String name) 方法为每个命名组提供起始位置。

使用 start 进行错误处理

在成功匹配之前或对于不存在的组调用 start 会抛出 IllegalStateException。此示例演示了在使用 start 方法时的正确错误处理。

StartErrorHandling.java
package com.zetcode;

import java.util.regex.*;

public class StartErrorHandling {
    public static void main(String[] args) {
        String text = "Sample text without matches";
        Pattern pattern = Pattern.compile("pattern");
        Matcher matcher = pattern.matcher(text);
        
        try {
            // This will throw IllegalStateException
            System.out.println("Start: " + matcher.start());
        } catch (IllegalStateException e) {
            System.out.println("Error: " + e.getMessage());
        }
        
        if (matcher.find()) {
            try {
                // This will throw IndexOutOfBoundsException
                System.out.println("Group 1 start: " + matcher.start(1));
            } catch (IndexOutOfBoundsException e) {
                System.out.println("Error: " + e.getMessage());
            }
        }
    }
}

此示例显示了两种常见的错误情况。首先,在尝试任何匹配之前调用 start。其次,请求不存在的组。这两种情况都会抛出异常,应在生产代码中进行适当处理。

将 start 与 Region 方法一起使用

在使用匹配器区域时,start 返回相对于原始输入字符串而不是区域的位置。此示例演示了区域限制搜索的这种行为。

RegionStartExample.java
package com.zetcode;

import java.util.regex.*;

public class RegionStartExample {
    public static void main(String[] args) {
        String text = "First match here and second match there";
        Pattern pattern = Pattern.compile("match");
        Matcher matcher = pattern.matcher(text);
        
        // Set region from index 15 to 30
        matcher.region(15, 30);
        
        while (matcher.find()) {
            System.out.println("Found '" + matcher.group() + 
                "' at position: " + matcher.start() + 
                " (region-relative: " + (matcher.start() - 15) + ")");
        }
    }
}

此代码将搜索限制为输入字符串的特定区域。虽然匹配器仅在区域内搜索,但 start 仍然返回原始字符串中的绝对位置。我们通过减去区域起始索引来计算区域相对位置。

性能注意事项

start 方法是一个轻量级操作,它只是返回一个存储的值。但是,为同一个匹配项重复调用它是不必要的。为了获得最佳性能,如果您需要多次使用结果,请将其存储在变量中。

PerformanceExample.java
package com.zetcode;

import java.util.regex.*;

public class PerformanceExample {
    public static void main(String[] args) {
        String text = "Testing performance of start() method";
        Pattern pattern = Pattern.compile("performance");
        Matcher matcher = pattern.matcher(text);
        
        if (matcher.find()) {
            // Good practice: store once, use multiple times
            int startPos = matcher.start();
            
            System.out.println("Match starts at: " + startPos);
            System.out.println("Context before: " + 
                text.substring(0, startPos));
            System.out.println("Context after: " + 
                text.substring(startPos));
        }
    }
}

此示例显示了将起始位置存储在变量中的推荐方法。这避免了对同一个匹配项多次调用 start。虽然性能影响很小,但这种做法可以使代码更简洁。

来源

Java MatchResult 文档

本教程深入介绍了 MatchResult.start 方法。我们探讨了基本用法、组处理、错误情况和性能提示。理解这些概念对于在 Java 中进行有效的文本处理至关重要。

作者

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

列出所有Java教程