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
相关产品推荐
相关产品推荐

