ZetCode

Java Matcher.lookingAt 方法

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

Matcher.lookingAt 方法是 Java 正则表达式 API 中的部分匹配操作。它尝试将输入序列的开头与模式进行匹配。与 matches 不同的是,它不需要整个输入都匹配。

如果输入序列的开头与模式匹配,则该方法返回 true。当您需要检查输入是否以特定模式开头时,它非常有用。该方法不需要整个字符串都匹配。

Matcher.lookingAt 概述

lookingAt 类似于 matches,但要求更宽松。虽然 matches 要求整个输入都与模式匹配,但 lookingAt 只检查开头。它比 matches 更灵活,但比 find 更严格。

该方法不会更改匹配器的状态。后续调用 lookingAt 将始终从输入的开头开始。它对于验证字符串中的输入前缀或标头很有用。

基本的 lookingAt 示例

此示例演示了 lookingAt 的基本用法。我们检查一个字符串是否以特定模式开头。如果输入的开头符合该模式,则该模式匹配。

LookingAtBasic.java
package com.zetcode;

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

public class LookingAtBasic {

    public static void main(String[] args) {
        
        String input = "Hello World!";
        Pattern pattern = Pattern.compile("Hello");
        Matcher matcher = pattern.matcher(input);
        
        boolean result = matcher.lookingAt();
        System.out.println("Does input start with 'Hello'? " + result);
        
        // Compare with matches()
        boolean fullMatch = matcher.matches();
        System.out.println("Does entire input match 'Hello'? " + fullMatch);
    }
}

在此示例中,lookingAt 返回 true,因为输入以 "Hello" 开头。但是,matches 返回 false,因为它要求整个字符串与模式匹配。

使用复杂模式的 lookingAt

lookingAt 与其他匹配方法一样,可以处理复杂的正则表达式模式。此示例演示了如何检查一个字符串是否以有效的日期格式开头。该模式包括数字和特定的分隔符。

LookingAtComplex.java
package com.zetcode;

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

public class LookingAtComplex {

    public static void main(String[] args) {
        
        String[] inputs = {
            "2023-05-15: Meeting at 10am",
            "15/05/2023: Team lunch",
            "Invalid date: May 15, 2023"
        };
        
        Pattern datePattern = Pattern.compile("\\d{4}-\\d{2}-\\d{2}");
        
        for (String input : inputs) {
            Matcher matcher = datePattern.matcher(input);
            boolean hasDate = matcher.lookingAt();
            System.out.printf("'%s' starts with date? %b%n", 
                input, hasDate);
        }
    }
}

此代码检查每个字符串是否以 YYYY-MM-DD 格式的日期开头。只有第一个字符串与该模式匹配。如果开头匹配,该方法会忽略日期之后的内容。这对于解析带有标头的结构化文本很有用。

lookingAt vs find vs matches

此示例将 lookingAtfindmatches 进行比较。每种方法都有不同的匹配行为。理解这些差异对于有效地使用正则表达式至关重要。

LookingAtComparison.java
package com.zetcode;

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

public class LookingAtComparison {

    public static void main(String[] args) {
        
        String input = "123 Main Street";
        Pattern pattern = Pattern.compile("\\d+");
        
        Matcher matcher = pattern.matcher(input);
        
        System.out.println("lookingAt(): " + matcher.lookingAt());
        System.out.println("find(): " + matcher.find());
        System.out.println("matches(): " + matcher.matches());
        
        // Reset matcher for fresh matching
        matcher.reset();
        
        System.out.println("\nAfter reset:");
        System.out.println("find() from start: " + matcher.find());
        System.out.println("Region matches: " + 
            matcher.region(0, 3).matches());
    }
}

lookingAt 返回 true,因为字符串以数字开头。find 也返回 true,因为它在任何地方找到了数字。matches 失败,因为它要求整个字符串都是数字。区域示例展示了如何将匹配限制到子字符串。

使用组的 lookingAt

lookingAt 支持捕获组,就像其他匹配方法一样。成功匹配后,可以提取组。此示例展示了如何将字符串的开头解析成各个组件。

LookingAtGroups.java
package com.zetcode;

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

public class LookingAtGroups {

    public static void main(String[] args) {
        
        String input = "ERROR 2023-05-15: Disk full";
        Pattern pattern = Pattern.compile(
            "(\\w+)\\s(\\d{4}-\\d{2}-\\d{2}):\\s(.*)");
        
        Matcher matcher = pattern.matcher(input);
        
        if (matcher.lookingAt()) {
            System.out.println("Full match: " + matcher.group(0));
            System.out.println("Log level: " + matcher.group(1));
            System.out.println("Date: " + matcher.group(2));
            System.out.println("Message: " + matcher.group(3));
        } else {
            System.out.println("No match found");
        }
    }
}

此代码解析日志条目格式。该模式捕获三个组:日志级别、日期和消息。lookingAt 确保整个模式从开头匹配。这些组允许访问匹配的特定部分。

使用多个模式的 lookingAt

此示例展示了如何将 lookingAt 与多个模式一起使用。我们检查哪个模式匹配输入的开头。此技术对于内容类型检测很有用。

LookingAtMultiple.java
package com.zetcode;

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

public class LookingAtMultiple {

    public static void main(String[] args) {
        
        String input = "<?xml version='1.0'?><root></root>";
        Pattern[] patterns = {
            Pattern.compile("<\\?xml.*\\?>"),  // XML declaration
            Pattern.compile("<html>"),        // HTML tag
            Pattern.compile("\\s*")           // Whitespace
        };
        
        for (Pattern pattern : patterns) {
            Matcher matcher = pattern.matcher(input);
            if (matcher.lookingAt()) {
                System.out.println("Matches: " + pattern.pattern());
                break;
            }
        }
    }
}

该代码检查哪个模式匹配 XML 字符串的开头。XML 声明模式首先匹配。该方法在第一个成功匹配处停止。这种方法对于格式检测很有效。

使用 Region 的 lookingAt

region 方法限制了 lookingAt 搜索的范围。此示例展示了如何检查输入特定部分的模式。区域对于解析结构化数据很有用。

LookingAtRegion.java
package com.zetcode;

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

public class LookingAtRegion {

    public static void main(String[] args) {
        
        String input = "Header: Value\nBody: Content";
        Pattern headerPattern = Pattern.compile("Header:");
        Pattern bodyPattern = Pattern.compile("Body:");
        
        Matcher matcher = headerPattern.matcher(input);
        
        // Check header at start
        System.out.println("Header at start: " + matcher.lookingAt());
        
        // Set region to after first line
        matcher.region(input.indexOf('\n') + 1, input.length());
        
        // Check body in region
        matcher.usePattern(bodyPattern);
        System.out.println("Body in region: " + matcher.lookingAt());
    }
}

此代码首先检查字符串开头是否有标头。然后,它设置一个区域到第一个换行符之后,并检查正文模式。区域限制使 lookingAt 仅考虑指定子字符串。

lookingAt 性能考量

此示例演示了 lookingAt 的性能方面。当您只需要检查开头时,该方法可能比 find 更有效。它避免了扫描整个输入。

LookingAtPerformance.java
package com.zetcode;

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

public class LookingAtPerformance {

    public static void main(String[] args) {
        
        String longInput = "START " + "x".repeat(1000000);
        Pattern pattern = Pattern.compile("START");
        
        long startTime = System.nanoTime();
        Matcher matcher = pattern.matcher(longInput);
        boolean result = matcher.lookingAt();
        long endTime = System.nanoTime();
        
        System.out.println("lookingAt took: " + 
            (endTime - startTime) + " ns");
        
        startTime = System.nanoTime();
        result = pattern.matcher(longInput).find();
        endTime = System.nanoTime();
        
        System.out.println("find took: " + 
            (endTime - startTime) + " ns");
    }
}

对于前缀检查,lookingAt 通常比 find 表现更好。它在检查输入开头后停止。这种差异在大型输入中变得显着。始终为您的需求选择最具体的匹配方法。

来源

Java Matcher.lookingAt 文档

在本文中,我们深入探讨了 Matcher.lookingAt 方法。这种部分匹配技术对于许多文本处理任务都很有价值。理解它的行为有助于编写高效而精确的正则表达式代码。

作者

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

列出所有Java教程