C# 正则表达式(Regex)入门 - 常用模式与匹配方法详解

C#正则表达式非必须但高效,核心是掌握高频场景写法与避坑点;常用模式包括手机号、邮箱、中文姓名、身份证号、日期、URL;按需选用IsMatch/Match/Matches/Replace;推荐命名捕获组和逐字字符串;避免贪婪匹配与灾难性回溯。

C# 中的正则表达式(Regex)不是必须学,但一旦用对了,能省下大量字符串处理代码。它本质是用一套紧凑语法描述文本模式,再由 .NET 的 System.Text.RegularExpressions.Regex 类执行匹配、提取、替换等操作。关键不在于背所有符号,而在于掌握高频场景下的写法和避坑点。

常用模式:从身份证、手机号到邮箱,怎么写才靠谱

写正则第一原则:**够用且不过度严格**。比如验证手机号,国内主流是 1[3-9]\d{9},但别硬套“必须11位+首位1+第二位3-9”,因为携号转网后可能有新号段;验证邮箱用 [^\s@]+@[^\s@]+\.[^\s@]+ 就比 RFC 5322 标准简化版更实用——后者太长,且多数业务根本不需要支持引号包裹的用户名或 IP 形式域名。

  • 中文姓名:^[\u4e00-\u9fa5]{2,4}$(2–4个汉字,不含空格标点)
  • 身份证号(18位):^\d{17}[\dXx]$(末位可能是 X,注意大小写)
  • 日期(YYYY-MM-DD):^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$(仅格式校验,不判断闰年或每月天数)
  • URL 简化版:^https?://[^\s/$.?#].[^\s]*$(跳过协议后校验是否有域名主体)

匹配方法选哪个?Match、Matches、IsMatch、Replace 各干啥

不用死记 API,按目标选:

  • 只关心“有没有匹配” → 用 Regex.IsMatch(input, pattern),返回 bool,最快最轻量
  • 要取第一个匹配内容(含分组) → Regex.Match(input, pattern),返回 Match

    对象,.Success 判断是否成功,.Value 拿全文,.Groups[1].Value 拿第一个捕获组
  • 要找所有匹配 → Regex.Matches(input, pattern),返回 MatchCollection,可 foreach 遍历
  • 要批量替换 → Regex.Replace(input, pattern, replacement),replacement 可以是字符串,也可以是 MatchEvaluator 委托实现动态逻辑(比如把所有数字加括号)

注意:如果 pattern 固定且反复使用,建议实例化 Regex 对象并启用 RegexOptions.Compiled(首次编译慢,后续快),或直接用静态方法——.NET Core 6+ 对静态调用做了缓存优化,日常小项目够用。

捕获组与命名组:不只是“取内容”,更是结构化提取

() 是捕获组,按左括号顺序编号(Groups[0] 是整个匹配,Groups[1] 是第一个 ())。但写多了容易乱,推荐命名组:(?\d{4})-(?\d{2})-(?\d{2})。匹配后可通过 match.Groups["year"].Value 直接读年份,语义清晰,重构友好。

还常配合 RegexOptions.IgnoreCase(忽略大小写)、RegexOptions.Multiline(^$ 匹配每行起止)等选项使用。例如多行日志里找 ERROR 行:^.*ERROR.*$ + Multiline,否则 ^$ 只匹配整个字符串头尾。

容易踩的坑:转义、贪婪、性能这三座山

正则里反斜杠是元字符,C# 字符串又吃反斜杠,所以写 \d 要么用双反斜杠 "\\d",要么用逐字字符串 @ "\d"——后者更清爽,推荐。

  • 贪婪匹配默认吃最多,比如 a.*ba123b456b 中会匹配整串;想只到第一个 b,改成懒惰模式:a.*?b
  • 避免灾难性回溯:像 (a+)+b 这类嵌套量词在坏输入下会让引擎指数级尝试,改用原子组 (?>a+)+b 或重写逻辑(比如先找 a 再找 b)
  • 简单场景别硬上正则:用 string.Containsstring.StartsWithint.TryParse 更快更安全;正则适合“模糊结构识别”,比如日志行中提取多个字段

基本上就这些。正则不是银弹,但它是文本处理工具箱里最锋利的小刀——磨熟了,切哪都快。