正则表达式匹配目标字符串不符合预期问题求助
嘿,我一眼就看出问题所在啦——你把**通配符里的*和正则表达式里的***搞混了,这俩完全不是一个东西!
问题根源
咱们平时用的通配符*(比如*a*m*)代表「任意长度的任意字符(包括0个字符)」,但正则里的*是量词,它的作用是修饰前面的字符,意思是「前面的字符出现0次或多次」。
举个你测试用例里的例子:你写的.*ad*.,这个正则的实际含义是:
.*:匹配任意字符0次或多次a:匹配字母ad*:匹配字母d出现0次或多次(注意,不是匹配d后面的任意字符!).:匹配任意单个字符
而你要匹配的admin是a-d-m-i-n,这个正则最后只能匹配到adm这部分,后面的in没地方放,所以matches()自然返回false了。
解决方案:把通配符转成正确的正则
你需要先把用户输入的通配符规则转换成符合正则语法的表达式,核心就是把通配符的*替换成正则里的.*(这才是正则里代表「任意字符任意次数」的写法)。另外还要注意转义正则的特殊字符,避免用户输入的搜索词里有.、+这类符号时出错。
我给你修正后的代码:
import java.util.regex.Matcher; import java.util.regex.Pattern; public class WildcardMatcher { public static void main(String args[]) { // 测试你的三个用例 System.out.println("测试1: " + matcher("*ad*", "admin")); // 应该返回true System.out.println("测试2: " + matcher("*max*", "max11")); // 应该返回true System.out.println("测试3: " + matcher("*sa*", "sam1")); // 应该返回true // 测试你预期的场景 System.out.println("测试*a*m*匹配admin: " + matcher("*a*m*", "admin")); // true System.out.println("测试*sam*匹配sam1: " + matcher("*sam*", "sam1")); // true System.out.println("测试m*匹配max: " + matcher("m*", "max")); // true System.out.println("测试max*匹配maximus: " + matcher("max*", "maximus")); // true } private static boolean matcher(String filterCriteria, String parentString) { String regex = wildcardToRegex(filterCriteria); Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(parentString); return matcher.matches(); } // 把通配符转换成正则表达式 private static String wildcardToRegex(String wildcard) { // 先转义所有正则特殊字符,再把通配符*替换成正则的.* return Pattern.quote(wildcard).replace("*", ".*"); } }
为什么这样改?
Pattern.quote(wildcard):把用户输入的搜索词里的所有正则特殊字符(比如.、+、?)转义,避免这些字符被当成正则语法解析。replace("*", ".*"):把通配符的*替换成正则里的「任意字符任意次数」表达式。- 因为
matches()方法本身就是匹配整个字符串,所以不需要额外加^(开头)和$(结尾),转换后的正则已经能满足全匹配要求。
这样修改后,你所有的测试用例和预期场景都能正确返回true啦!
内容的提问来源于stack exchange,提问作者Rohit Shekhar
相关产品推荐
相关产品推荐

