C#如何在字符串中查找符合通配规则的目标子串
字符串模糊匹配效率问题
我有如下字符串(长度可能更长):
string list = "ABCDGGWWWW1234567 ABCDGGWWWW1234568 ABCDGGWWWW1234569 ";
需要判断子串ABCDGGWWWW1234568是否存在于该字符串中,原本用如下代码即可实现:
list.IndexOf("ABCDGGWWWW1234568 ") >= 0;
现在有新需求:如果搜索的子串为ABCDXXWWWW1234568,也需要返回true。规则说明:待匹配字符串固定为17位大写字符,第5、6位要么是原值要么是XX,不会出现仅单字符替换的情况。
我之前尝试直接用下划线、问号作为通配符写了如下代码:
list.IndexOf("ABCD__WWWW1234568 ") >= 0; list.IndexOf("ABCD??WWWW1234568 ") >= 0;
但运行后一直返回-1,无法生效。目前参考@PanagiotisKanavos的方案,通过正则实现了功能:
chassis = chassis.Substring(0, 4) + @"\S{2}" + chassis.Substring(6, 11) + @"\s+"; bool result = Regex.IsMatch(list, chassis);
请问实现该需求的最高效方式是什么?
回答
首先string.IndexOf本身不支持通配符语法,下划线、问号会被当做普通字符匹配,因此无法生效。
最高效的实现方式取决于使用场景:
1. 超高性能场景(高频调用/待匹配字符串超长)
直接做两次精确匹配即可,规则只允许第5、6位是原值或XX,不需要引入通配符:
// 输入的待匹配模板串,示例为"ABCDGGWWWW1234568" string targetTemplate = "ABCDGGWWWW1234568"; string targetOrigin = targetTemplate; string targetXX = targetTemplate.Substring(0,4) + "XX" + targetTemplate.Substring(6); // 任意一个匹配成功就返回true bool isExist = list.IndexOf(targetOrigin) >= 0 || list.IndexOf(targetXX) >= 0;
该方案性能比正则高1~2个数量级,原因:
- 直接调用系统底层优化过的字符串匹配逻辑,无正则表达式的解析、编译开销
- 逻辑严谨,不会出现正则通配符匹配到非预期字符的问题
- 代码简单易维护,没有额外依赖
2. 规则可扩展场景
如果后续可能调整通配规则,可以使用预编译正则降低开销:
// 正则提前静态编译,全局只初始化一次 private static readonly Regex _chassisMatchRegex = new Regex(@"ABCD(?:GG|XX)WWWW1234568", RegexOptions.Compiled); // 调用时直接匹配 bool result = _chassisMatchRegex.IsMatch(list);
如果模板是动态生成的,可以调整为:
string prefix = Regex.Escape(chassis.Substring(0,4)); string midOrigin = Regex.Escape(chassis.Substring(4,2)); string suffix = Regex.Escape(chassis.Substring(6)); Regex dynamicRegex = new Regex($"{prefix}(?:{midOrigin}|XX){suffix}", RegexOptions.Compiled); bool result = dynamicRegex.IsMatch(list);
内容的提问来源于stack exchange,提问作者GuidoG
相关产品推荐
相关产品推荐

