regex.match 用于提取单个匹配值,轻量安全;regex.matches 配合 foreach 遍历全部匹配项,避免直接索引 matchcollection 导致性能浪费。

只提取一个值,用 Regex.Match;要拿全部匹配项,必须用 Regex.Matches 配合 foreach;别直接索引访问 MatchCollection,那是性能陷阱。
只取第一个匹配结果,Regex.Match 是默认选择
它返回单个 Match 对象,轻量、安全、语义清晰。比如从日志行里找第一个 IP 地址、从 SQL 语句里取首个参数名、验证输入是否含有效邮箱——这些场景都该用它。
-
Match.Success必须检查,否则Match.Value可能抛NullReferenceException - 不要写
Regex.Match(input, pattern).Value这种裸调用,先判.Success - 如果正则带
^或$,且你要匹配每行开头/结尾,得加RegexOptions.Multiline,否则它们只锚定整个字符串首尾
要遍历所有匹配项,Regex.Matches 返回的是 MatchCollection,不是数组
它不支持 [0]、[i] 索引访问。常见错误是写成 Regex.Matches(input, pattern)[0] ——表面取第一个,实则内部已全量扫描,浪费 CPU 和内存。
- 正确做法:用
foreach (Match m in Regex.Matches(input, pattern)) { ... } - 如果真需要列表(比如后续要随机访问或 LINQ 操作),显式转:
Regex.Matches(input, pattern).Cast<match>().ToList()</match> - 注意
MatchCollection是延迟执行的,Count属性会触发完整扫描,慎用
提取括号、引号、尖括号这类包围结构的内容,关键在非贪婪和边界控制
比如提取双引号内内容,"hello" 和 "he\"llo" 是不同难度。简单场景可用 "(.*?)",但遇到转义或嵌套就失效。
- 基础提取(无转义):
Regex.Match(input, "\"([^\"]*)\"").Groups[1].Value - 中括号内容:
Regex.Matches(input, @"\[(.*?)\]"),注意?防止跨多组匹配 - 小括号内容:
@"\(.*?\)",若需排除嵌套,正则本身力不从心,得换语法分析器 - 大括号内容(如 JSON 片段):
Regex.Match(input, @"\{([^{}]*)\}", RegexOptions.Singleline),加Singleline让.匹配换行符
提取数字、中文、邮箱等常用数据,别硬造正则,优先复用成熟模式
自己写的 [0-9]+ 看似简单,但漏掉负数、小数、科学计数法;[\u4e00-\u9fa5]+ 能抓中文,但不含中文标点或扩展区汉字(如 emoji 字符、古籍用字)。
- 纯整数提取:
Regex.Replace(str, @"[^0-9-]+", "")不够,建议用Regex.Matches(str, @"-?\d+")更准 - 邮箱验证别用“全能正则”,
Regex.IsMatch(email, @"^[^\s@]+@[^\s@]+\.[^\s@]+$")足够日常过滤,RFC 5322 全兼容正则长达上千字符,没必要 - 提取多个邮箱:
Regex.Matches(text, @"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"),注意域名后缀长度限制 - 性能敏感场景(如日志实时解析),避免
RegexOptions.Compiled:.NET Core 3.0+ 已优化 JIT 编译路径,多数情况反而更慢
最常被忽略的一点:正则不是万能解析器。遇到 HTML 标签嵌套、JSON 结构、带转义的字符串,硬用正则提取容易漏匹配或崩溃。该上 HtmlAgilityPack 就别省那几行代码,该用 System.Text.Json 就别写 @"\{.*?\}"。











