正则表达式匹配结果不符合预期,请求分析错误原因
你的正则与Split搭配出错的原因及修复方案
首先得说,你搞反了正则的用途——你的正则是用来匹配整个符合规则的完整字符串的,但你却把它当成Split的分隔符来用,再加上.NET的Split对捕获组的特殊处理,才导致结果完全不符合预期。
为什么会得到奇怪的结果?
你的正则(f|s|t)(\d+(f|s|t))*,其实是匹配f20s30t整个字符串的:
- 第一个捕获组
(f|s|t)匹配到开头的f; - 后面的
(\d+(f|s|t))*会重复匹配数字加字母的组合,最后一次匹配到的是30t,所以第二个捕获组是30t,第三个嵌套捕获组是t。
而.NET的Regex.Split有个特殊行为:如果正则里包含捕获组,它会把捕获到的内容也加入拆分结果数组。当你用整个匹配的字符串作为分隔符时,最终得到的数组是["", "f", "30t", "t", ""],过滤空字符串后就变成了你看到的f、30t、t。
正确的解决思路
你想要的是提取f、20s、30t这类片段,最直接的方式是匹配提取,而不是用Split拆分。如果一定要用Split,也得找对分隔的位置。
方法一:用匹配提取(推荐)
直接写一个能匹配目标片段的正则:要么是单个f/s/t,要么是数字+f/s/t。可以把两种情况合并成简洁的\d*[fst](\d*允许0个数字,刚好覆盖单个字母的情况),然后用Regex.Matches提取所有匹配项:
string input = "f20s30t"; var matches = Regex.Matches(input, @"\d*[fst]"); foreach (Match m in matches) { Console.WriteLine(m.Value); // 输出:f、20s、30t }
方法二:用Split实现(如果坚持用Split)
Split需要找到每个目标片段的起始位置,也就是在f/s/t前面的位置(除了字符串开头)。可以用正向前瞻断言(?=[fst])——它只会匹配一个位置,后面跟着f/s/t,但不会消耗任何字符,这样拆分出来的就是刚好的片段:
string input = "f20s30t"; var parts = Regex.Split(input, @"(?=[fst])").Where(p => !string.IsNullOrEmpty(p)).ToArray(); foreach (string part in parts) { Console.WriteLine(part); // 输出:f、20s、30t }
内容的提问来源于stack exchange,提问作者Tirafesi
相关产品推荐
相关产品推荐

