You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java Regex Matcher跳过未知字符未抛出异常问题如何解决

问题原因
  • Matcher.find()方法的默认逻辑是从当前扫描位置向后查找任意可匹配的子串,不会要求必须从当前位置立刻匹配成功,因此中间无法匹配的@字符会被直接跳过,直到找到后方可匹配的54为止。
  • 你当前没有校验两次匹配的连续性,所以无法感知到中间被跳过的非法字符。
  • 额外说明:你当前拼接的总正则存在规则冗余,[0-9]+(\\.([0-9])+)?已经可以匹配整数和浮点数,额外拼接的[0-9]+完全多余,还会导致后续判断Token类型时出现匹配优先级问题。
修改方案

每次匹配完成后记录匹配的结束位置,下一次匹配前校验新的匹配起始位置是否和上一次的结束位置一致,存在错位就直接抛出异常;全部匹配完成后还要校验是否覆盖了整个输入字符串,避免末尾残留非法字符。

参考实现代码:

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

// 优化正则,用捕获分组区分不同Token类型,方便后续判断
private static final Pattern TOKEN_PATTERN = Pattern.compile(
    "([0-9]+\\.[0-9]+)" + // 分组1:浮点数
    "|([+])" + // 分组2:加号
    "|([*])" + // 分组3:乘号
    "|([0-9]+)" // 分组4:整数
);

public void parseInput(String input) throws InvalidInputException {
    Matcher matcher = TOKEN_PATTERN.matcher(input);
    int lastEnd = 0;
    while (matcher.find()) {
        // 校验是否有被跳过的非法字符
        if (matcher.start() != lastEnd) {
            throw new InvalidInputException("存在非法字符:" + input.substring(lastEnd, matcher.start()));
        }
        // 处理Token生成逻辑,通过匹配的分组判断Token类型
        String tokenValue = matcher.group();
        if (matcher.group(1) != null) {
            // 生成浮点数类型Token
        } else if (matcher.group(2) != null) {
            // 生成加号类型Token
        } else if (matcher.group(3) != null) {
            // 生成乘号类型Token
        } else if (matcher.group(4) != null) {
            // 生成整数类型Token
        }
        // 更新上一次匹配的结束位置
        lastEnd = matcher.end();
    }
    // 校验末尾是否有剩余未匹配的非法字符
    if (lastEnd != input.length()) {
        throw new InvalidInputException("存在非法字符:" + input.substring(lastEnd));
    }
}

内容的提问来源于stack exchange,提问作者bitcasual

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 22:48:02