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# 技术干货!如果觉得有用,记得收藏本文

相关推荐
wyzqhhhh2 小时前
京东啊啊啊啊啊
开发语言·前端·javascript
JIngJaneIL2 小时前
基于java+ vue助农电商系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
想学后端的前端工程师2 小时前
【Java集合框架深度解析:从入门到精通-后端技术栈】
前端·javascript·vue.js
VcB之殇2 小时前
git常用操作合集
前端·git
yinuo3 小时前
前端跨页面通讯终极指南⑧:Cookie 用法全解析
前端
小鑫同学3 小时前
vue-pdf-interactor 技术白皮书:为现代 Web 应用注入交互式 PDF 能力
前端·vue.js·github
GISer_Jing3 小时前
Nano Banana:AI图像生成与编辑新标杆
前端·javascript·人工智能
云中飞鸿3 小时前
值类型、引用类型
c#
gyx_这个杀手不太冷静3 小时前
上线前不做 Code Review?你可能正在给团队埋雷!
前端·代码规范·团队管理