c#正则表达式
在 C# 中,正则表达式是处理文本模式匹配和字符串操作的强大工具,通过System.Text.RegularExpressions
命名空间提供支持。以下是关于 C# 正则表达式的详细介绍:
1. 基本概念
正则表达式是用于定义字符串模式的字符序列,可用于:
验证输入格式(如邮箱、手机号)
提取特定内容(如 URL、日期)
替换或分割字符串
核心类:
Regex
:表示编译后的正则表达式。Match
:表示单个匹配结果。MatchCollection
:表示多个匹配结果的集合。Group
:表示捕获组(括号内的子表达式)。
2. 常用元字符和语法
元字符 | 含义 | 示例 |
---|---|---|
. | 匹配任意单个字符(除换行符) | a.b 匹配 acb |
^ | 匹配字符串开头 | ^Hello 匹配以Hello 开头的字符串 |
$ | 匹配字符串结尾 | world$ 匹配以world 结尾的字符串 |
* | 匹配前面的元素 0 次或多次 | ab* 匹配 a 、ab 、abb 等 |
+ | 匹配前面的元素 1 次或多次 | ab+ 匹配 ab 、abb ,但不匹配 a |
? | 匹配前面的元素 0 次或 1 次 | ab? 匹配 a 或 ab |
{n} | 匹配前面的元素恰好 n 次 | a{3} 匹配 aaa |
{n,} | 匹配前面的元素至少 n 次 | a{2,} 匹配 aa 、aaa 等 |
{n,m} | 匹配前面的元素 n 到 m 次 | a{2,3} 匹配 aa 或 aaa |
[] | 匹配方括号内的任意一个字符 | [abc] 匹配 a 、b 或 c |
[^] | 匹配不在方括号内的任意字符 | [^abc] 匹配除 a 、b 、c 外的字符 |
| | 或运算,匹配左侧或右侧的模式 | a|b 匹配 a 或 b |
() | 分组,用于捕获子表达式或优先级 | (ab)+ 匹配 ab 、abab 等 |
3. 预定义字符类
字符类 | 等价于 | 含义 |
---|---|---|
\d | [0-9] | 匹配数字 |
\D | [^0-9] | 匹配非数字 |
\w | [a-zA-Z0-9_] | 匹配字母、数字或下划线 |
\W | [^a-zA-Z0-9_] | 匹配非字母、数字或下划线 |
\s | [ \t\n\r\f\v] | 匹配空白字符(空格、制表符等) |
\S | [^ \t\n\r\f\v] | 匹配非空白字符 |
4. 量词的贪婪与非贪婪模式
贪婪模式(默认):尽可能多地匹配。
"aabab".Match("a.*b") // 匹配 "aabab"(最长匹配)
非贪婪模式(? 后加):尽可能少地匹配。
"aabab".Match("a.*?b") // 匹配 "aab"(最短匹配)
5. C# 中的正则表达式用法
5.1 创建正则表达式
using System.Text.RegularExpressions; // 方式1:直接创建实例 Regex regex = new Regex(@"pattern"); // 方式2:静态方法(自动缓存) Match match = Regex.Match(input, @"pattern");
5.2 常用方法
方法 | 描述 |
---|---|
IsMatch(input) | 检查输入是否匹配模式 |
Match(input) | 返回第一个匹配结果 |
Matches(input) | 返回所有匹配结果的集合 |
Replace(input, replacement) | 替换匹配的文本 |
Split(input) | 根据匹配结果分割字符串 |
6. 示例代码
6.1 验证邮箱格式
string email = "test@example.com"; bool isValid = Regex.IsMatch(email, @"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"); // 输出:True
6.2 提取 URL 中的域名
string url = "https://www.example.com/path"; Match match = Regex.Match(url, @"https?://([^/]+)"); if (match.Success) {string domain = match.Groups[1].Value; // 输出:www.example.com }
6.3 替换文本中的数字
string input = "Hello 123 World 456"; string result = Regex.Replace(input, @"\d+", "NUMBER"); // 输出:Hello NUMBER World NUMBER
6.4 分割字符串
string input = "Hello,World;Foo Bar"; string[] parts = Regex.Split(input, @"[,\s;]+"); // 输出:["Hello", "World", "Foo", "Bar"]
7. 性能优化
静态方法:对于频繁使用的正则表达式,优先使用静态方法(如
Regex.Match
),因为它们会自动缓存编译后的表达式。编译选项:使用
RegexOptions.Compiled
可将表达式编译为程序集,提高性能(适用于多次使用的复杂模式)。
Regex regex = new Regex(@"pattern", RegexOptions.Compiled);
懒惰求值:使用
Matches
方法时,结果是延迟计算的,避免一次性加载所有匹配项。
8. 注意事项
转义字符:在正则表达式中使用反斜杠\时,需要在 C# 字符串中写为\,或使用逐字字符串@"..."
@"\\d" // 等价于 "\\\\d",匹配反斜杠后接数字
回溯陷阱:复杂的正则表达式可能导致性能问题,例如嵌套量词(如
(a+)*
)会引发指数级回溯。
9. 常用正则表达式模式
手机号:
^1[3-9]\d{9}$
IPv4 地址:
^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
HTML 标签:
<[^>]+>
日期(YYYY-MM-DD):
^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$
通过掌握这些基础知识,你可以在 C# 中灵活运用正则表达式处理各种文本操作。如果需要更复杂的模式或性能优化,可以进一步研究RegexOptions
和捕获组的高级用法。
具体例子:
以下是 C# 正则表达式的具体例子和使用方法,涵盖常见场景和 API 用法:
1. 验证类示例
1.1 验证手机号
string phone = "13800138000"; bool isValid = Regex.IsMatch(phone, @"^1[3-9]\d{9}$"); // 输出:True
1.2 验证密码强度(至少 8 位,包含大小写字母和数字)
string password = "Passw0rd"; bool isStrong = Regex.IsMatch(password, @"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$"); // 输出:True
2. 提取类示例
2.1 从 HTML 中提取所有 URL
string html = "<a href='https://example.com'>Link</a> <img src='image.jpg'>"; MatchCollection matches = Regex.Matches(html, @"https?://\S+"); foreach (Match match in matches) {Console.WriteLine(match.Value); // 输出:https://example.com }
2.2 提取日期中的年、月、日
string date = "2023-10-01"; Match match = Regex.Match(date, @"(\d{4})-(\d{2})-(\d{2})"); if (match.Success) {string year = match.Groups[1].Value; // 2023string month = match.Groups[2].Value; // 10string day = match.Groups[3].Value; // 01 }
3. 替换类示例
3.1 敏感信息脱敏(手机号中间 4 位替换为星号)
string phone = "13800138000"; string masked = Regex.Replace(phone, @"(\d{3})\d{4}(\d{4})", "$1****$2"); // 输出:138****8000
3.2 替换 HTML 标签为纯文本
string html = "<p>Hello <b>World</b>!</p>"; string text = Regex.Replace(html, @"<[^>]*>", ""); // 输出:Hello World!
4. 分割类示例
4.1 按逗号或空格分割字符串
string input = "Apple, Banana Orange;Grape"; string[] fruits = Regex.Split(input, @"[,\s;]+"); // 输出:["Apple", "Banana", "Orange", "Grape"]
5. 高级用法
5.1 忽略大小写匹配
string text = "Hello World"; bool isMatch = Regex.IsMatch(text, @"world", RegexOptions.IgnoreCase); // 输出:True
5.2 多行模式匹配
string text = "Line 1\nLine 2\nLine 3"; MatchCollection matches = Regex.Matches(text, @"^Line \d", RegexOptions.Multiline); // 匹配所有以"Line"开头的行
5.3 正向预查(查找后面跟特定内容的文本)
string text = "apple$10, banana$20"; MatchCollection matches = Regex.Matches(text, @"\w+(?=\$\d+)"); // 输出:["apple", "banana"]
6. 完整代码示例
以下是一个完整的程序,演示如何使用正则表达式提取网页中的邮箱地址:
using System; using System.Text.RegularExpressions; class Program {static void Main() {string html = @"<p>Contact us at support@example.com or info@company.net</p><a href='mailto:admin@domain.com'>Admin</a>"; // 定义邮箱正则表达式string pattern = @"[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+";// 执行匹配MatchCollection matches = Regex.Matches(html, pattern);// 输出结果Console.WriteLine("找到的邮箱地址:");foreach (Match match in matches) {Console.WriteLine(match.Value);}} } /* 输出: 找到的邮箱地址: support@example.com info@company.net admin@domain.com */
7. 常用正则表达式模式
场景 | 正则表达式模式 | 说明 |
---|---|---|
邮箱验证 | ^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$ | 简单邮箱格式验证 |
身份证号验证 | ^\d{17}[\dXx]$ | 18 位身份证号(含 X 结尾) |
URL 验证 | ^https?://[^\s/$.?#].[^\s]*$ | 验证 HTTP/HTTPS URL |
数字验证 | ^-?\d+(\.\d+)?$ | 整数或小数 |
汉字验证 | ^[\u4e00-\u9fa5]+$ | 纯中文字符 |
8. 性能优化建议
重复使用同一正则表达式:编译开销较大,建议创建静态实例:
private static readonly Regex EmailRegex = new Regex(@"[a-z]+@[a-z]+\.[a-z]+");
避免回溯陷阱:复杂嵌套量词(如
(a+)*
)可能导致指数级性能下降。使用非捕获组:不需要提取内容时,用
(?:pattern)
代替(pattern)
减少内存开销。
掌握这些例子和方法后,你可以处理大多数文本处理场景。如需更复杂的模式,可以组合使用不同的元字符和选项。