C# 正则表达式:量词与锚点——从“.*”到精确匹配

一、量词:告诉引擎"要重复多少次"

量词出现在一个"单元"后面,表示这个单元要重复多少次。

单元可以是:

  • 一个普通字符:a
  • 一个字符类:\d[A-Z]
  • 一个分组:(ab)

1. 常见量词一览

  • ?:0 或 1 次
  • *:0 次或多次
  • +:1 次或多次
  • {n}:恰好 n 次
  • {n,}:至少 n 次
  • {n,m}:n 到 m 次之间

示例:

csharp 复制代码
using System.Text.RegularExpressions;

string pattern = @"^\d{3,5}$"; 
bool ok = Regex.IsMatch("1234", pattern); // True

2. 量词是作用在"前一项"上的

注意:ab+ 只会把 + 作用到 b 上:

  • 模式:ab+
    • 匹配:"ab"、"abb"、"abbbb"...
  • 模式:(ab)+
    • 匹配:"ab"、"abab"、"ababab"...

也就是说,当你想对一"串"东西使用量词,一定要用括号分组。


二、贪婪 vs 懒惰:**? 的根本区别

量词在默认情况下是"贪婪"的:

  • 在不影响匹配成功的前提下,尽可能多地吃字符。

1. 贪婪匹配:.*

csharp 复制代码
string input = "<tag>content</tag><tag>more</tag>";
string pattern = @"<tag>.*</tag>";

Match m = Regex.Match(input, pattern);
Console.WriteLine(m.Value);

匹配结果:

text 复制代码
<tag>content</tag><tag>more</tag>
  • .* 会尽可能多地吃字符,直到最后一个满足条件的 </tag>

2. 懒惰匹配:.*?

在量词后面再加一个 ?,就变成"懒惰"(即最多满足一次):

  • *?:尽可能少的 0 次或多次
  • +?:尽可能少的 1 次或多次
  • ??:尽可能少的 0 或 1 次
  • {n,m}?:在 n~m 之间,尽量少

改写上面的例子:

csharp 复制代码
string pattern = @"<tag>.*?</tag>";

Match m = Regex.Match(input, pattern);
Console.WriteLine(m.Value);

匹配结果:

text 复制代码
<tag>content</tag>

三、用量词写几个常见"格式":

1. 简单日期:yyyy-MM-dd

regex 复制代码
^\d{4}-\d{2}-\d{2}$
  • 不考虑合法性,只看格式

2. 用户名:字母开头,后面 3~15 位字母数字下划线

regex 复制代码
^[A-Za-z]\w{3,15}$
  • [A-Za-z]:首字符必须是字母
  • \w{3,15}:后面 3~15 个字母数字下划线
  • 总长度:4~16

C#:

csharp 复制代码
string pattern = @"^[A-Za-z]\w{3,15}$";
bool ok = Regex.IsMatch("User_001", pattern);

3. 整数和小数

简单版本的"非负整数或小数":

regex 复制代码
^\d+(\.\d+)?$
  • \d+:至少一位数字
  • (\.\d+)?:可选的小数部分(. + 至少一位数字)

匹配:01233.140.5 不匹配:..53.(如果你想放宽,可以调整)。


四、锚点:决定"匹配的是不是整串"

锚点(Anchor)是一类特殊的"零宽"匹配,只匹配"位置",不消耗字符。

1)^:开头,$:结尾

默认情况下:

  • ^ 匹配字符串的开头;
  • $ 匹配字符串的结尾。

示例:

regex 复制代码
^abc      // 匹配以 "abc" 开头的字符串
abc$      // 匹配以 "abc" 结尾的字符串
^abc$     // 字符串只能是 "abc"
csharp 复制代码
Regex.IsMatch("abc123", @"^abc");   // True
Regex.IsMatch("123abc", @"abc$");   // True
Regex.IsMatch("xabcx", @"^abc$");   // False

2. 表单校验一定要写 ^$

csharp 复制代码
// 不严谨
Regex.IsMatch("abc2025-12-18xyz", @"\d{4}-\d{2}-\d{2}"); 
// True,只要"包含"符合格式的子串就通过

// 严谨
Regex.IsMatch("abc2025-12-18xyz", @"^\d{4}-\d{2}-\d{2}$");
// False,整个字符串不是完整日期

3. 字符类里的 ^ 意义完全不同

regex 复制代码
^abc        // 锚点:开头
[^abc]      // 取反:匹配任何不是a、b、c的字符
  • ^[] 外:开头锚点
  • ^[] 里且在首位:表示"取反",方括号内的字符任意组合的反面

五、单词边界:\b

\b 是"单词边界"(word boundary),匹配"从一个 \w 字符到一个非 \w 字符的边界"。

例子:

csharp 复制代码
string text = "cat scat category";
string pattern = @"\bcat\b";

MatchCollection matches = Regex.Matches(text, pattern);
foreach (Match m in matches)
{
    Console.WriteLine(m.Value);
}

输出:

text 复制代码
cat

解析:

  • "cat" 前后都是边界(左边是开头,右边是空格),满足 \b
  • "scat" 中的 cat 左边是 s,属于 \w,不会被 \bcat\b 匹配。
  • "category" 中的 cat 右边是 e,也是 \w,也不符合。

六、多行模式(Multiline)与单行模式(Singleline)

C# 中用 RegexOptions 可以控制 ^ / $. 的行为。

1. RegexOptions.Multiline:多行模式

默认情况:

csharp 复制代码
string text = "first\nsecond\nthird";
string pattern = @"^second$";

Console.WriteLine(Regex.IsMatch(text, pattern)); // False

因为:

  • ^$ 在默认模式下只匹配整个字符串起始和结尾,不会感知行。

多行模式开启后:

csharp 复制代码
bool ok = Regex.IsMatch(
    text,
    pattern,
    RegexOptions.Multiline
);
Console.WriteLine(ok); // True

此时:

  • ^ / $ 会匹配每一行的开头/结尾(以 \n 作为换行)。

2. RegexOptions.Singleline:单行模式 / DOTALL

默认情况下:

  • . 不匹配换行符。
csharp 复制代码
string text = "line1\nline2";
string pattern = @".*";

Match m1 = Regex.Match(text, pattern);
Console.WriteLine(m1.Value);    // "line1"

开启 Singleline 后:

csharp 复制代码
Match m2 = Regex.Match(text, pattern, RegexOptions.Singleline);
Console.WriteLine(m2.Value);    // "line1\nline2"

此时:

  • . 会匹配包括换行在内的任何字符。

总结一下:

  • Multiline:影响 ^ / $,让它们感知"行"
  • Singleline:影响 .,让 . 能匹配换行

它们可以一起用:

csharp 复制代码
var regex = new Regex(
    pattern,
    RegexOptions.Multiline | RegexOptions.Singleline
);

结语

点个赞,关注我获取更多实用 C# 技术干货!如果觉得有用,记得收藏本文

相关推荐
崔庆才丨静觅3 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60614 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了4 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅4 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅5 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
懒人咖5 小时前
缺料分析时携带用料清单的二开字段
c#·金蝶云星空
崔庆才丨静觅5 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment5 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅5 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊6 小时前
jwt介绍
前端