阅读视图

发现新文章,点击刷新页面。

C# 正则表达式(2):Regex 基础语法与常用 API 全解析

一、IsMatch 入门

using System;
using System.Text.RegularExpressions;

class Program
{
    static void Main()
    {
        string input = "2025-12-18";
        string pattern = @"^\d{4}-\d{2}-\d{2}$";

        bool isValid = Regex.IsMatch(input, pattern);
        Console.WriteLine(isValid); // True
    }
}

解析:

  • pattern 是正则表达式,@"..." 是 C# 的逐字字符串字面量。
  • ^$:锚点,表示“从头到尾整串匹配”
  • \d{4}:4 位数字。
  • -:字面量“-”。
  • Regex.IsMatch:看字符串中是不是“满足这个模式”。

二、C# Regex 的 5 个核心方法

System.Text.RegularExpressions.Regex 里,最常用的就是这 5 个方法:

  1. IsMatch
  2. Match
  3. Matches
  4. Replace
  5. Split

三、Regex.IsMatch:最常用的“判断是否匹配”

IsMatch 是表单校验、输入合法性检查中使用频率最高的方法。

bool isEmail = Regex.IsMatch(email, pattern);

示例:

string input = "Order12345";
string pattern = @"\d{3}";

bool has3Digits = Regex.IsMatch(input, pattern); // True

注意点:

  • 默认只要“包含”满足 pattern 的子串,就返回 true,并不要求整个字符串都完全匹配。
  • 如果你想“整个字符串必须符合这个规则”,要在 pattern 外面加上 ^$
// 只允许由 3~5 位数字组成,不允许多一个字符
string pattern = @"^\d{3,5}$";

四、Regex.Match:获取第一个匹配

string text = "My phone is 123-456-7890.";
string pattern = @"\d{3}-\d{3}-\d{4}";

Match match = Regex.Match(text, pattern);
if (match.Success)
{
    Console.WriteLine(match.Value);  // "123-456-7890"
    Console.WriteLine(match.Index);  // 起始索引
    Console.WriteLine(match.Length); // 匹配的长度
}

常用成员:

  • match.Success:是否匹配成功。
  • match.Value:匹配到的字符串。
  • match.Index:匹配在原文本中的起始位置(从 0 开始)。
  • match.Length:长度。

Regex.Match 也有带起始位置、带 RegexOptions 的重载:


五、Regex.Matches:获取所有匹配结果(多个)

string text = "ID: 100, 200, 300";
string pattern = @"\d+";

MatchCollection matches = Regex.Matches(text, pattern);
foreach (Match m in matches)
{
    Console.WriteLine($"{m.Value} at {m.Index}");
}
// 输出:
// 100 at 4
// 200 at 9
// 300 at 14

解析:

  • 返回的是一个 MatchCollection,可以 foreach 遍历。
  • 每个 Match 和前面一样,有 ValueIndexGroups 等属性。

六、Regex.Replace:按模式搜索并替换

Regex.Replace 和字符串的 Replace 很像,但支持模式匹配。

1. 固定字符串替换匹配内容

string input = "2025/12/18";
string pattern = @"/";

string result = Regex.Replace(input, pattern, "-");
Console.WriteLine(result); // "2025-12-18"

这相当于“把所有 / 都换成 -”,和 input.Replace("/", "-") 类似,但 pattern 可以写得更复杂。

2.用捕获组重排内容

string input = "2025-12-18";
string pattern = @"(\d{4})-(\d{2})-(\d{2})";

// 把 yyyy-MM-dd 改成 dd/MM/yyyy
string result = Regex.Replace(input, pattern, "$3/$2/$1");
// result: "18/12/2025"

解析:

这里的 $1$2$3 是捕获组

3. 更高级的 MatchEvaluator 版本

string input = "Price: 100 USD, 200 USD";
string pattern = @"(\d+)\s*USD";

string result = Regex.Replace(input, pattern, m =>
{
    int value = int.Parse(m.Groups[1].Value);
    int converted = (int)(value * 7.2); // 假设汇率
    return $"{converted} CNY";
});

Console.WriteLine(result);
// "Price: 720 CNY, 1440 CNY"

七、Regex.Split:按“模式”切割字符串

可以实现多分隔符的切割

string input = "apple, banana; cherry|date";
string pattern = @"[,;|]\s*"; // 逗号;分号;竖线 + 可选空白

string[] parts = Regex.Split(input, pattern);

foreach (var p in parts)
{
    Console.WriteLine(p);
}
// apple
// banana
// cherry
// date

八、正则基础语法(一):字面字符与转义

1. 字面字符

绝大多数普通字符在正则里就是字面意思:

  • 模式:abc → 匹配文本中出现的 abc
  • 模式:hello → 匹配文本中出现的 hello

2. 特殊字符(元字符)

这些字符在正则中有特殊含义:

  • . ^ $ * + ? ( ) [ ] { } \ |

如果你要匹配其中任意一个“字面意义上的”字符,就要用 \ 转义。

例如:

  • 匹配一个点号 . → 模式 \.
  • 匹配一个星号 * → 模式 \*
  • 匹配一对括号 (abc) → 模式 \( + abc + \)

在 C# 中配合逐字字符串:

string pattern = @"\.";   // 匹配 "."
string pattern2 = @"\*";  // 匹配 "*"

如果不用 @

string pattern = "\\.";   // C# 字符串里写成 "\\." 才表示一个反斜杠+点

实践中几乎所有正则字符串都用 @"",可以少一半反斜杠。


九、正则基础语法(二):预定义字符类 \d / \w / \s

预定义字符类是正则里最常用的工具,它们代表一类字符。

1. \d / \D:数字与非数字

  • \d:digit,匹配 0–9 的任意一位数字,相当于 [0-9]
  • \D:非数字,相当于 [^0-9]

示例:匹配一个或多个数字

string pattern = @"\d+";

2. \w / \W:单词字符与非单词字符

  • \w:word,匹配字母、数字和下划线,相当于 [A-Za-z0-9_]
  • \W:非 \w

示例:匹配“单词”(一串字母数字下划线)

string pattern = @"\w+";

3. \s / \S:空白字符与非空白字符

  • \s:space,匹配空格、制表符、换行等所有空白字符。
  • \S:非空白。

示例:

string pattern = @"\s+"; // 匹配一个或多个空白

结语

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

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

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

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

单元可以是:

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

1. 常见量词一览

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

示例:

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. 贪婪匹配:.*

string input = "<tag>content</tag><tag>more</tag>";
string pattern = @"<tag>.*</tag>";

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

匹配结果:

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

2. 懒惰匹配:.*?

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

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

改写上面的例子:

string pattern = @"<tag>.*?</tag>";

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

匹配结果:

<tag>content</tag>

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

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

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

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

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

C#:

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

3. 整数和小数

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

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

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


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

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

1)^:开头,$:结尾

默认情况下:

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

示例:

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

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

// 不严谨
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. 字符类里的 ^ 意义完全不同

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

五、单词边界:\b

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

例子:

string text = "cat scat category";
string pattern = @"\bcat\b";

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

输出:

cat

解析:

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

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

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

1. RegexOptions.Multiline:多行模式

默认情况:

string text = "first\nsecond\nthird";
string pattern = @"^second$";

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

因为:

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

多行模式开启后:

bool ok = Regex.IsMatch(
    text,
    pattern,
    RegexOptions.Multiline
);
Console.WriteLine(ok); // True

此时:

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

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

默认情况下:

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

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

开启 Singleline 后:

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

此时:

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

总结一下:

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

它们可以一起用:

var regex = new Regex(
    pattern,
    RegexOptions.Multiline | RegexOptions.Singleline
);

结语

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

❌