Regex.Match 只返回第一个匹配是设计行为而非 bug;应使用 Regex.Matches 获取全部结果,注意 Unicode 匹配需用 \p{L}\p{N} 等 Unicode 类,命名捕获组替换用 ${name},多行模式需显式指定 RegexOptions.Multiline。

Regex.Match 只返回第一个匹配,不是 bug,是设计如此;要拿全部结果,必须用 Regex.Matches。
为什么 Regex.Match 总是只找到一个就停了
它本质就是单次扫描:从字符串开头起,找到第一个能完整匹配的位置就立刻返回 Match 对象,不往后看。这不是遗漏,是行为契约。
- 常见误操作:
Match m = Regex.Match(s, pattern); while (m.Success) { ... m = m.NextMatch(); }—— 容易漏掉重叠匹配,且NextMatch()在无后续匹配时返回空Match(Success == false),但很多人没检查直接进循环 - 真正安全的做法:直接调用
Regex.Matches(input, pattern),拿到MatchCollection后foreach遍历 - 如果正则里用了
^或$,默认按整个字符串首尾锚定;多行文本需显式加RegexOptions.Multiline,否则每行中间的^不生效
Regex.Replace 怎么保留原始内容中的部分字段
别手动拼接 match.Groups[1].Value,用捕获组占位符才是正解——它天然处理非匹配段、边界和重复替换逻辑。
- 写法示例:
Regex.Replace(input, @"(\d+)-(\w+)", "ID:$1-Code:$2"),其中$1和$2自动代入括号内捕获的内容 - 命名组要用
${name},不是$name;漏掉花括号会当字面量处理 - .NET 6+ 支持格式化语法如
${num:000},旧版本不认,直接当普通文本输出 - 如果想对每个匹配做不同逻辑(比如根据值动态生成替换内容),才用委托重载:
Regex.Replace(input, pattern, match => ComputeReplacement(match))
中文、emoji 或 Unicode 字符总匹配失败怎么办
根本原因不是正则写错,而是默认字符类(\w、.、\b)只识别 ASCII 范围,遇到中文或 emoji 就失效。
-
\w+匹配不了 “测试123”,因为\w在 .NET 默认不包含汉字;改用[\p{L}\p{N}]+(\p{L}表示任意字母,含中文;\p{N}表示任意数字) -
.默认不跨 surrogate pair(如大部分 emoji),即使开了RegexOptions.Singleline;若需匹配任意 Unicode 字符,用[\s\S]或[\u0000-\U0010FFFF] - 锚定行为也受 Unicode 影响:
\b在中英文混排时可能断在不该断的地方;建议明确用(? / <code>(?=$|\s)替代
RegexOptions.Compiled 该不该加
它不是“越加越快”,而是一把双刃剑:首次构造慢、内存占用高、JIT 优化受限,仅在高频复用场景下才值得。
- 静态复用的正则(如
private static readonly Regex EmailRegex = new(@"^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$", RegexOptions.Compiled))适合加 - 临时一次性使用的
Regex.Match(input, pattern)形式,加了反而更慢,且不会触发编译路径 - .NET 6+ 对短小正则做了自动内联优化,
Compiled的优势进一步缩小;实际项目中,优先实测Stopwatch对比再决定 - 注意:编译后的
Regex实例不可序列化,存到缓存或跨 AppDomain 传递会失败
Unicode 边界、捕获组占位符、Matches 与 Match 的语义差异——这些不是细节,是 C# 正则真正容易出错的核心点。


















