C# 正则表达式完全指南
C#通过 System.Text.RegularExpressions
命名空间提供强大的正则表达式支持。本指南将详细介绍C#中正则表达式的使用方法、性能优化和最佳实践。
1. 基础知识
1.1 命名空间导入
csharp
using System.Text.RegularExpressions;
1.2 基本使用
csharp
public class RegexBasics
{
public void BasicExamples()
{
string text = "Hello, my phone is 123-456-7890";
// 创建正则表达式对象
Regex regex = new Regex(@"\d+");
// 检查是否匹配
bool isMatch = regex.IsMatch(text);
// 查找第一个匹配
Match match = regex.Match(text);
if (match.Success)
{
Console.WriteLine($"Found: {match.Value}");
}
// 查找所有匹配
MatchCollection matches = regex.Matches(text);
foreach (Match m in matches)
{
Console.WriteLine($"Found: {m.Value}");
}
}
}
1.3 正则表达式选项
csharp
public class RegexOptions
{
public void OptionsExample()
{
// 不区分大小写
Regex caseInsensitive = new Regex(@"hello", RegexOptions.IgnoreCase);
// 多行模式
Regex multiline = new Regex(@"^start", RegexOptions.Multiline);
// 忽略空白字符和注释
Regex ignored = new Regex(@"
\d+ # 匹配数字
\s* # 可选的空白字符
\w+ # 匹配单词
", RegexOptions.IgnorePatternWhitespace);
// 编译正则表达式以提高性能
Regex compiled = new Regex(@"\d+", RegexOptions.Compiled);
}
}
2. 正则表达式语法
2.1 字符匹配
csharp
public class CharacterMatching
{
public void MatchingExamples()
{
string text = "C# 10.0 is awesome! Price: $99.99";
// 匹配数字
Regex digits = new Regex(@"\d+");
foreach (Match m in digits.Matches(text))
{
Console.WriteLine($"Number: {m.Value}");
}
// 匹配单词
Regex words = new Regex(@"\w+");
var wordMatches = words.Matches(text)
.Cast<Match>()
.Select(m => m.Value)
.ToList();
// 匹配空白字符
string[] parts = Regex.Split(text, @"\s+");
// 自定义字符类
Regex vowels = new Regex(@"[aeiou]", RegexOptions.IgnoreCase);
var vowelMatches = vowels.Matches(text)
.Cast<Match>()
.Select(m => m.Value)
.ToList();
}
}
2.2 分组和捕获
csharp
public class GroupingExample
{
public void GroupExamples()
{
string text = "John Smith, Jane Doe, Bob Johnson";
// 基本分组
Regex regex = new Regex(@"(\w+)\s(\w+)");
foreach (Match match in regex.Matches(text))
{
Console.WriteLine($"Full name: {match.Groups[0].Value}");
Console.WriteLine($"First name: {match.Groups[1].Value}");
Console.WriteLine($"Last name: {match.Groups[2].Value}");
}
// 命名分组
Regex namedRegex = new Regex(@"(?<first>\w+)\s(?<last>\w+)");
foreach (Match match in namedRegex.Matches(text))
{
Console.WriteLine($"First: {match.Groups["first"].Value}");
Console.WriteLine($"Last: {match.Groups["last"].Value}");
}
}
}
3. 高级特性
3.1 替换操作
csharp
public class ReplacementOperations
{
public string ReplaceExample(string text)
{
// 简单替换
string result1 = Regex.Replace(text, @"\d+", "X");
// 使用MatchEvaluator委托
string result2 = Regex.Replace(text, @"\d+", match =>
{
int number = int.Parse(match.Value);
return (number * 2).ToString();
});
// 使用命名组的替换
Regex regex = new Regex(@"(?<first>\w+)\s(?<last>\w+)");
string result3 = regex.Replace(text, "${last}, ${first}");
return result3;
}
}
3.2 前瞻和后顾
csharp
public class LookAroundExample
{
public void LookAroundDemo()
{
string text = "Price: $100, Cost: $50";
// 正向前瞻
Regex positiveAhead = new Regex(@"\d+(?=\s*dollars)");
// 负向前瞻
Regex negativeAhead = new Regex(@"\d+(?!\s*dollars)");
// 正向后顾
Regex positiveBehind = new Regex(@"(?<=\$)\d+");
// 负向后顾
Regex negativeBehind = new Regex(@"(?<!\$)\d+");
}
}
4. 实用工具类
4.1 验证器
csharp
public class Validator
{
private static readonly Regex EmailRegex = new Regex(
@"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$",
RegexOptions.Compiled);
private static readonly Regex PhoneRegex = new Regex(
@"^1[3-9]\d{9}$",
RegexOptions.Compiled);
private static readonly Regex PasswordRegex = new Regex(
@"^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$",
RegexOptions.Compiled);
public static bool IsValidEmail(string email)
{
if (string.IsNullOrEmpty(email)) return false;
return EmailRegex.IsMatch(email);
}
public static bool IsValidPhone(string phone)
{
if (string.IsNullOrEmpty(phone)) return false;
return PhoneRegex.IsMatch(phone);
}
public static bool IsValidPassword(string password)
{
if (string.IsNullOrEmpty(password)) return false;
return PasswordRegex.IsMatch(password);
}
}
4.2 文本处理器
csharp
public class TextProcessor
{
private static readonly Regex UrlRegex = new Regex(
@"https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+[^\s]*",
RegexOptions.Compiled);
private static readonly Regex HtmlTagRegex = new Regex(
@"<[^>]+>",
RegexOptions.Compiled);
public static IEnumerable<string> ExtractUrls(string text)
{
if (string.IsNullOrEmpty(text)) return Enumerable.Empty<string>();
return UrlRegex.Matches(text)
.Cast<Match>()
.Select(m => m.Value);
}
public static string StripHtmlTags(string html)
{
if (string.IsNullOrEmpty(html)) return string.Empty;
return HtmlTagRegex.Replace(html, string.Empty);
}
public static string CleanWhitespace(string text)
{
if (string.IsNullOrEmpty(text)) return string.Empty;
return Regex.Replace(text.Trim(), @"\s+", " ");
}
}
5. 性能优化
5.1 静态编译正则表达式
csharp
public class RegexOptimization
{
// 使用静态字段存储编译后的正则表达式
private static readonly Regex CompiledRegex = new Regex(
@"\d+",
RegexOptions.Compiled);
// 使用Lazy<T>延迟初始化
private static readonly Lazy<Regex> LazyRegex =
new Lazy<Regex>(() => new Regex(@"\d+", RegexOptions.Compiled));
public void OptimizedExample()
{
// 使用编译后的正则表达式
bool isMatch = CompiledRegex.IsMatch("123");
// 使用延迟初始化的正则表达式
bool lazyMatch = LazyRegex.Value.IsMatch("123");
}
}
5.2 性能考虑
csharp
public class PerformanceConsiderations
{
// 1. 使用适当的选项
private static readonly Regex FastRegex = new Regex(
@"\d+",
RegexOptions.Compiled | RegexOptions.ExplicitCapture);
// 2. 避免过度使用通配符
private static readonly Regex BetterRegex = new Regex(
@"[^/]*foo[^/]*", // 比 .*foo.* 更高效
RegexOptions.Compiled);
// 3. 使用非捕获组
private static readonly Regex NonCapturingRegex = new Regex(
@"(?:\d+)(?:[a-z]+)", // 使用(?:)表示非捕获组
RegexOptions.Compiled);
}
6. 异常处理
csharp
public class RegexExceptionHandling
{
public static Regex CreateSafeRegex(string pattern)
{
try
{
return new Regex(pattern, RegexOptions.Compiled);
}
catch (ArgumentException ex)
{
throw new ArgumentException($"Invalid regex pattern: {ex.Message}", ex);
}
}
public static bool SafeIsMatch(string input, string pattern)
{
try
{
return Regex.IsMatch(input, pattern);
}
catch (RegexMatchTimeoutException ex)
{
Console.WriteLine($"Regex matching timed out: {ex.Message}");
return false;
}
catch (ArgumentException ex)
{
Console.WriteLine($"Invalid regex pattern: {ex.Message}");
return false;
}
}
}
7. 单元测试
csharp
[TestClass]
public class ValidatorTests
{
[TestMethod]
public void TestEmailValidation()
{
Assert.IsTrue(Validator.IsValidEmail("test@example.com"));
Assert.IsTrue(Validator.IsValidEmail("user@domain.co.uk"));
Assert.IsFalse(Validator.IsValidEmail("invalid.email"));
Assert.IsFalse(Validator.IsValidEmail("@domain.com"));
}
[TestMethod]
public void TestPhoneValidation()
{
Assert.IsTrue(Validator.IsValidPhone("13812345678"));
Assert.IsFalse(Validator.IsValidPhone("12345678"));
Assert.IsFalse(Validator.IsValidPhone("2381234567"));
}
[TestMethod]
public void TestTextProcessing()
{
string html = "<p>Hello</p><div>World</div>";
Assert.AreEqual(
"HelloWorld",
TextProcessor.StripHtmlTags(html)
);
string text = " multiple spaces here ";
Assert.AreEqual(
"multiple spaces here",
TextProcessor.CleanWhitespace(text)
);
}
}
总结
C#的正则表达式实现具有以下特点:
- 强大的Regex类支持
- 编译选项提供高性能
- LINQ集成
- 完整的Unicode支持
最佳实践:
- 使用静态编译的Regex对象提高性能
- 合理使用RegexOptions
- 处理超时和异常情况
- 编写完整的单元测试
- 使用命名捕获组提高可读性
注意事项:
- Regex对象创建开销大,应该重用
- 考虑使用Compiled选项提高性能
- 处理RegexMatchTimeoutException
- 注意内存使用
记住:在C#中使用正则表达式时,要充分利用.NET框架提供的功能,如编译选项和LINQ集成。合理使用静态编译和缓存可以显著提高性能。