C# 正则表达式完全指南
正则表达式在C#中的主要用途
| 用途类别 | 具体应用场景 | 示例说明 |
|---|---|---|
| 数据验证 | 表单验证、输入校验 | 验证邮箱、电话、身份证号等格式是否正确 |
| 文本搜索 | 查找特定模式的文本 | 在日志中查找错误代码、特定时间戳等 |
| 文本替换 | 批量修改文本内容 | 统一格式化日期、清理多余空格等 |
| 字符串分割 | 按复杂规则分割字符串 | 按多个分隔符分割CSV文件等 |
| 数据提取 | 从文本中提取结构化信息 | 从HTML中提取链接、从日志中提取IP地址等 |
| 文本分析 | 统计词频、分析模式 | 分析代码中的函数调用、统计关键词出现次数 |
让用户自定义维护正则表达式的方法
1. 配置文件方案
csharp
// 在appsettings.json中配置
{
"ValidationRules": {
"Email": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
"Phone": "^1[3-9]\\d{9}$",
"IdCard": "^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$"
}
}
// C#代码读取配置
public class RegexValidator
{
private readonly IConfiguration _configuration;
public RegexValidator(IConfiguration configuration)
{
_configuration = configuration;
}
public bool Validate(string ruleName, string input)
{
var pattern = _configuration[$"ValidationRules:{ruleName}"];
if (string.IsNullOrEmpty(pattern))
throw new ArgumentException($"规则 {ruleName} 未配置");
return Regex.IsMatch(input, pattern);
}
}
2. 数据库存储方案
csharp
// 数据库表设计
public class ValidationRule
{
public int Id { get; set; }
public string RuleName { get; set; }
public string Pattern { get; set; }
public string Description { get; set; }
public bool IsActive { get; set; }
}
// 动态验证服务
public class DynamicRegexValidator
{
private readonly AppDbContext _context;
public DynamicRegexValidator(AppDbContext context)
{
_context = context;
}
public async Task<ValidationResult> ValidateAsync(string ruleName, string input)
{
var rule = await _context.ValidationRules
.FirstOrDefaultAsync(r => r.RuleName == ruleName && r.IsActive);
if (rule == null)
return new ValidationResult { IsValid = false, Message = "规则不存在" };
bool isValid = Regex.IsMatch(input, rule.Pattern);
return new ValidationResult
{
IsValid = isValid,
Message = isValid ? "验证通过" : $"不符合{rule.Description}格式"
};
}
}
3. 用户界面配置方案
csharp
// 简单的规则管理界面
public class RegexRuleManager
{
private Dictionary<string, string> _rules = new Dictionary<string, string>();
public void AddRule(string name, string pattern, string testString = null)
{
// 验证正则表达式是否有效
try
{
if (!string.IsNullOrEmpty(testString))
{
Regex.Match(testString, pattern);
}
_rules[name] = pattern;
}
catch (ArgumentException ex)
{
throw new Exception($"正则表达式格式错误: {ex.Message}");
}
}
public bool Validate(string ruleName, string input)
{
if (_rules.ContainsKey(ruleName))
{
return Regex.IsMatch(input, _rules[ruleName]);
}
throw new ArgumentException($"规则 {ruleName} 不存在");
}
public List<string> ExtractMatches(string ruleName, string input)
{
if (!_rules.ContainsKey(ruleName))
throw new ArgumentException($"规则 {ruleName} 不存在");
var matches = Regex.Matches(input, _rules[ruleName]);
return matches.Select(m => m.Value).ToList();
}
}
完整实战示例
csharp
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace RegexMaster
{
class Program
{
static void Main(string[] args)
{
// 创建可配置的验证器
var validator = new ConfigurableRegexValidator();
// 添加用户自定义规则
validator.AddRule("ChinesePhone", "^1[3-9]\\d{9}$", "中国大陆手机号");
validator.AddRule("Email", "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", "电子邮箱");
validator.AddRule("StrongPassword", "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$", "强密码");
// 测试验证
TestValidation(validator);
// 测试数据提取
TestExtraction(validator);
}
static void TestValidation(ConfigurableRegexValidator validator)
{
Console.WriteLine("=== 数据验证测试 ===");
var testCases = new[]
{
new { Rule = "ChinesePhone", Value = "13812345678", Expected = true },
new { Rule = "ChinesePhone", Value = "12345678901", Expected = false },
new { Rule = "Email", Value = "test@example.com", Expected = true },
new { Rule = "Email", Value = "invalid-email", Expected = false },
new { Rule = "StrongPassword", Value = "Password123!", Expected = true },
new { Rule = "StrongPassword", Value = "weak", Expected = false }
};
foreach (var test in testCases)
{
bool result = validator.Validate(test.Rule, test.Value);
Console.WriteLine($"{test.Rule}({test.Value}) : {result} {(result == test.Expected ? "✓" : "✗")}");
}
}
static void TestExtraction(ConfigurableRegexValidator validator)
{
Console.WriteLine("\n=== 数据提取测试 ===");
string text = "联系我:13812345678 或 13987654321,邮箱:test@example.com, admin@site.org";
// 提取所有手机号
var phones = validator.ExtractMatches("ChinesePhone", text);
Console.WriteLine($"提取到的手机号: {string.Join(", ", phones)}");
// 提取所有邮箱
var emails = validator.ExtractMatches("Email", text);
Console.WriteLine($"提取到的邮箱: {string.Join(", ", emails)}");
}
}
// 可配置的正则表达式验证器
public class ConfigurableRegexValidator
{
private Dictionary<string, (string Pattern, string Description)> _rules
= new Dictionary<string, (string, string)>();
public void AddRule(string name, string pattern, string description = "")
{
// 验证正则表达式语法是否正确
try
{
Regex.Match("", pattern);
_rules[name] = (pattern, description);
Console.WriteLine($"规则 '{name}' 添加成功: {description}");
}
catch (ArgumentException ex)
{
throw new Exception($"无效的正则表达式 '{pattern}': {ex.Message}");
}
}
public bool Validate(string ruleName, string input)
{
if (_rules.TryGetValue(ruleName, out var rule))
{
return Regex.IsMatch(input, rule.Pattern);
}
throw new ArgumentException($"规则 '{ruleName}' 未定义");
}
public List<string> ExtractMatches(string ruleName, string input)
{
if (!_rules.TryGetValue(ruleName, out var rule))
throw new ArgumentException($"规则 '{ruleName}' 未定义");
var matches = Regex.Matches(input, rule.Pattern);
var results = new List<string>();
foreach (Match match in matches)
{
if (match.Success)
results.Add(match.Value);
}
return results;
}
public string Replace(string ruleName, string input, string replacement)
{
if (!_rules.TryGetValue(ruleName, out var rule))
throw new ArgumentException($"规则 '{ruleName}' 未定义");
return Regex.Replace(input, rule.Pattern, replacement);
}
}
}
进阶技巧:正则表达式性能优化
csharp
public class OptimizedRegexValidator
{
// 使用编译后的正则表达式提高性能
private static Dictionary<string, Regex> _compiledRegex = new Dictionary<string, Regex>();
public void AddCompiledRule(string name, string pattern, RegexOptions options = RegexOptions.None)
{
// 编译正则表达式,适合频繁使用的模式
var regex = new Regex(pattern, options | RegexOptions.Compiled);
_compiledRegex[name] = regex;
}
public bool ValidateFast(string ruleName, string input)
{
if (_compiledRegex.TryGetValue(ruleName, out var regex))
{
return regex.IsMatch(input);
}
throw new ArgumentException($"规则 '{ruleName}' 未定义");
}
// 使用静态正则表达式避免重复编译
private static readonly Regex EmailRegex = new Regex(
@"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$",
RegexOptions.Compiled | RegexOptions.IgnoreCase);
public static bool IsValidEmail(string email)
{
return EmailRegex.IsMatch(email);
}
}
学习路径建议
- 初级阶段 :掌握基本元字符
. * ? + [] () {} ^ $ - 中级阶段:学习分组、回溯引用、零宽断言
- 高级阶段:理解性能优化、复杂模式设计
- 大师阶段:能够设计可维护的正则系统,处理复杂文本处理场景
通过这种可配置的方式,你可以让非技术人员也能维护验证规则,大大提高了程序的灵活性和可维护性!
C# 正则表达式在企业级开发中的详细应用
实际开发场景:Excel规则配置系统
1. 数据库设计(Entity Framework Core)
csharp
// Models/RegexRule.cs
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
public class RegexRule
{
[Key]
public int Id { get; set; }
[Required]
[StringLength(100)]
public string RuleName { get; set; } // 规则名称
[Required]
[Column(TypeName = "nvarchar(max)")]
public string Pattern { get; set; } // 正则表达式模式
[StringLength(500)]
public string Description { get; set; } // 规则描述
[StringLength(50)]
public string Category { get; set; } // 分类:验证、提取、替换等
[StringLength(1000)]
public string TestExample { get; set; } // 测试用例
public bool IsActive { get; set; } = true; // 是否启用
public DateTime CreatedTime { get; set; } = DateTime.Now;
public DateTime UpdatedTime { get; set; } = DateTime.Now;
// 用于Excel导入导出的虚拟属性
[NotMapped]
public string ExcelStatus { get; set; } // 导入状态:成功/失败/错误信息
}
// Models/DataProcessLog.cs
public class DataProcessLog
{
public int Id { get; set; }
public string RuleName { get; set; }
public string InputData { get; set; }
public string OutputData { get; set; }
public bool Success { get; set; }
public string ErrorMessage { get; set; }
public DateTime ProcessTime { get; set; } = DateTime.Now;
}
2. Excel导入导出服务
csharp
// Services/ExcelRuleService.cs
using OfficeOpenXml;
using System.Collections.Generic;
using System.IO;
using System.Linq;
public class ExcelRuleService
{
private readonly ApplicationDbContext _context;
public ExcelRuleService(ApplicationDbContext context)
{
_context = context;
ExcelPackage.LicenseContext = LicenseContext.NonCommercial; // EPPlus许可证
}
// 导出规则到Excel
public byte[] ExportRulesToExcel()
{
using var package = new ExcelPackage();
var worksheet = package.Workbook.Worksheets.Add("正则规则");
// 设置表头
worksheet.Cells[1, 1].Value = "规则名称";
worksheet.Cells[1, 2].Value = "正则模式";
worksheet.Cells[1, 3].Value = "规则描述";
worksheet.Cells[1, 4].Value = "分类";
worksheet.Cells[1, 5].Value = "测试用例";
worksheet.Cells[1, 6].Value = "是否启用";
// 获取数据
var rules = _context.RegexRules.ToList();
// 填充数据
for (int i = 0; i < rules.Count; i++)
{
worksheet.Cells[i + 2, 1].Value = rules[i].RuleName;
worksheet.Cells[i + 2, 2].Value = rules[i].Pattern;
worksheet.Cells[i + 2, 3].Value = rules[i].Description;
worksheet.Cells[i + 2, 4].Value = rules[i].Category;
worksheet.Cells[i + 2, 5].Value = rules[i].TestExample;
worksheet.Cells[i + 2, 6].Value = rules[i].IsActive ? "是" : "否";
}
// 设置样式
worksheet.Cells[1, 1, 1, 6].Style.Font.Bold = true;
worksheet.Cells.AutoFitColumns();
return package.GetAsByteArray();
}
// 从Excel导入规则
public ImportResult ImportRulesFromExcel(Stream fileStream)
{
var result = new ImportResult();
var rulesToImport = new List<RegexRule>();
using var package = new ExcelPackage(fileStream);
var worksheet = package.Workbook.Worksheets[0];
int rowCount = worksheet.Dimension.Rows;
for (int row = 2; row <= rowCount; row++) // 跳过表头
{
var rule = new RegexRule
{
RuleName = worksheet.Cells[row, 1].Value?.ToString(),
Pattern = worksheet.Cells[row, 2].Value?.ToString(),
Description = worksheet.Cells[row, 3].Value?.ToString(),
Category = worksheet.Cells[row, 4].Value?.ToString(),
TestExample = worksheet.Cells[row, 5].Value?.ToString(),
IsActive = worksheet.Cells[row, 6].Value?.ToString() == "是"
};
// 验证数据
var validationResult = ValidateRule(rule);
if (validationResult.IsValid)
{
rulesToImport.Add(rule);
result.SuccessCount++;
}
else
{
result.ErrorMessages.Add($"第{row}行: {validationResult.ErrorMessage}");
}
}
// 保存到数据库
if (rulesToImport.Any())
{
_context.RegexRules.AddRange(rulesToImport);
_context.SaveChanges();
}
return result;
}
private ValidationResult ValidateRule(RegexRule rule)
{
if (string.IsNullOrWhiteSpace(rule.RuleName))
return ValidationResult.Fail("规则名称不能为空");
if (string.IsNullOrWhiteSpace(rule.Pattern))
return ValidationResult.Fail("正则模式不能为空");
// 验证正则表达式语法
try
{
System.Text.RegularExpressions.Regex.Match("", rule.Pattern);
}
catch (ArgumentException ex)
{
return ValidationResult.Fail($"正则表达式语法错误: {ex.Message}");
}
return ValidationResult.Success();
}
}
public class ImportResult
{
public int SuccessCount { get; set; }
public List<string> ErrorMessages { get; set; } = new List<string>();
}
public class ValidationResult
{
public bool IsValid { get; set; }
public string ErrorMessage { get; set; }
public static ValidationResult Success() => new ValidationResult { IsValid = true };
public static ValidationResult Fail(string message) => new ValidationResult { IsValid = false, ErrorMessage = message };
}
3. 核心正则处理引擎
csharp
// Services/RegexProcessingEngine.cs
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
public class RegexProcessingEngine
{
private readonly ApplicationDbContext _context;
private readonly Dictionary<string, Regex> _compiledRules;
public RegexProcessingEngine(ApplicationDbContext context)
{
_context = context;
_compiledRules = new Dictionary<string, Regex>();
LoadCompiledRules();
}
private void LoadCompiledRules()
{
var activeRules = _context.RegexRules
.Where(r => r.IsActive)
.ToList();
foreach (var rule in activeRules)
{
try
{
var regex = new Regex(rule.Pattern, RegexOptions.Compiled);
_compiledRules[rule.RuleName] = regex;
}
catch
{
// 记录日志,跳过无效规则
Console.WriteLine($"规则 '{rule.RuleName}' 编译失败");
}
}
}
// 数据验证
public ValidationResult ValidateData(string ruleName, string input)
{
if (!_compiledRules.ContainsKey(ruleName))
return ValidationResult.Fail($"规则 '{ruleName}' 不存在或未启用");
bool isValid = _compiledRules[ruleName].IsMatch(input);
return isValid ? ValidationResult.Success() : ValidationResult.Fail("数据格式不符合要求");
}
// 数据提取
public List<string> ExtractData(string ruleName, string input)
{
if (!_compiledRules.ContainsKey(ruleName))
return new List<string>();
var matches = _compiledRules[ruleName].Matches(input);
return matches.Select(m => m.Value).ToList();
}
// 数据替换
public string ReplaceData(string ruleName, string input, string replacement)
{
if (!_compiledRules.ContainsKey(ruleName))
return input;
return _compiledRules[ruleName].Replace(input, replacement);
}
// 批量处理Excel数据
public List<DataProcessResult> ProcessExcelData(List<ExcelDataRow> dataRows, string ruleName, ProcessType processType)
{
var results = new List<DataProcessResult>();
foreach (var row in dataRows)
{
var result = new DataProcessResult { RowId = row.RowId, OriginalData = row.Data };
try
{
switch (processType)
{
case ProcessType.Validate:
result.Success = ValidateData(ruleName, row.Data).IsValid;
break;
case ProcessType.Extract:
result.ExtractedData = ExtractData(ruleName, row.Data);
break;
case ProcessType.Replace:
result.ProcessedData = ReplaceData(ruleName, row.Data, row.Replacement);
break;
}
}
catch (Exception ex)
{
result.Success = false;
result.ErrorMessage = ex.Message;
}
results.Add(result);
}
return results;
}
}
public class ExcelDataRow
{
public int RowId { get; set; }
public string Data { get; set; }
public string Replacement { get; set; } // 用于替换操作
}
public class DataProcessResult
{
public int RowId { get; set; }
public string OriginalData { get; set; }
public string ProcessedData { get; set; }
public List<string> ExtractedData { get; set; }
public bool Success { get; set; }
public string ErrorMessage { get; set; }
}
public enum ProcessType
{
Validate,
Extract,
Replace
}
4. Web API 控制器
csharp
// Controllers/RegexRuleController.cs
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
[ApiController]
[Route("api/[controller]")]
public class RegexRuleController : ControllerBase
{
private readonly ExcelRuleService _excelService;
private readonly RegexProcessingEngine _processingEngine;
private readonly ApplicationDbContext _context;
public RegexRuleController(ExcelRuleService excelService,
RegexProcessingEngine processingEngine,
ApplicationDbContext context)
{
_excelService = excelService;
_processingEngine = processingEngine;
_context = context;
}
// 导出规则到Excel
[HttpGet("export")]
public IActionResult ExportRules()
{
var fileBytes = _excelService.ExportRulesToExcel();
return File(fileBytes,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
$"正则规则_{DateTime.Now:yyyyMMddHHmmss}.xlsx");
}
// 从Excel导入规则
[HttpPost("import")]
public async Task<ActionResult<ImportResult>> ImportRules(IFormFile file)
{
if (file == null || file.Length == 0)
return BadRequest("请选择文件");
using var stream = file.OpenReadStream();
var result = _excelService.ImportRulesFromExcel(stream);
return Ok(result);
}
// 处理Excel数据
[HttpPost("process-excel")]
public async Task<ActionResult> ProcessExcelData([FromBody] ProcessExcelRequest request)
{
var results = _processingEngine.ProcessExcelData(request.DataRows,
request.RuleName,
request.ProcessType);
// 记录处理日志
var logs = results.Select(r => new DataProcessLog
{
RuleName = request.RuleName,
InputData = r.OriginalData,
OutputData = r.ProcessedData ?? string.Join(";", r.ExtractedData ?? new List<string>()),
Success = r.Success,
ErrorMessage = r.ErrorMessage
}).ToList();
_context.DataProcessLogs.AddRange(logs);
await _context.SaveChangesAsync();
return Ok(new { Results = results, TotalCount = results.Count });
}
// 获取所有规则
[HttpGet("rules")]
public IActionResult GetRules()
{
var rules = _context.RegexRules
.Where(r => r.IsActive)
.Select(r => new
{
r.Id,
r.RuleName,
r.Pattern,
r.Description,
r.Category,
r.TestExample
})
.ToList();
return Ok(rules);
}
}
public class ProcessExcelRequest
{
public List<ExcelDataRow> DataRows { get; set; }
public string RuleName { get; set; }
public ProcessType ProcessType { get; set; }
}
5. 前端界面示例(Vue.js + Element UI)
html
<!-- 规则管理界面 -->
<template>
<div class="regex-rule-manager">
<el-card>
<template #header>
<div class="card-header">
<span>正则规则管理</span>
<div>
<el-button @click="exportRules">导出Excel</el-button>
<el-button type="primary" @click="importDialogVisible = true">导入Excel</el-button>
<el-button type="success" @click="addDialogVisible = true">新增规则</el-button>
</div>
</div>
</template>
<el-table :data="rules" style="width: 100%">
<el-table-column prop="ruleName" label="规则名称"></el-table-column>
<el-table-column prop="pattern" label="正则模式"></el-table-column>
<el-table-column prop="description" label="描述"></el-table-column>
<el-table-column prop="category" label="分类"></el-table-column>
<el-table-column label="操作">
<template #default="scope">
<el-button size="small" @click="testRule(scope.row)">测试</el-button>
<el-button size="small" type="danger" @click="deleteRule(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<!-- 数据处理器 -->
<el-card style="margin-top: 20px;">
<template #header>
<span>Excel数据处理</span>
</template>
<el-form :model="processForm" label-width="100px">
<el-form-item label="选择规则">
<el-select v-model="processForm.ruleName" placeholder="请选择规则">
<el-option
v-for="rule in rules"
:key="rule.ruleName"
:label="rule.ruleName"
:value="rule.ruleName">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="处理类型">
<el-radio-group v-model="processForm.processType">
<el-radio label="Validate">验证</el-radio>
<el-radio label="Extract">提取</el-radio>
<el-radio label="Replace">替换</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="Excel数据">
<el-input
type="textarea"
:rows="5"
v-model="processForm.excelData"
placeholder="每行一条数据,替换操作需要两列数据用逗号分隔">
</el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="processData">开始处理</el-button>
</el-form-item>
</el-form>
<!-- 处理结果 -->
<el-table :data="processResults" v-if="processResults.length > 0">
<el-table-column prop="rowId" label="行号"></el-table-column>
<el-table-column prop="originalData" label="原始数据"></el-table-column>
<el-table-column prop="processedData" label="处理结果"></el-table-column>
<el-table-column prop="success" label="状态">
<template #default="scope">
<el-tag :type="scope.row.success ? 'success' : 'danger'">
{{ scope.row.success ? '成功' : '失败' }}
</el-tag>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</template>
<script>
export default {
data() {
return {
rules: [],
processForm: {
ruleName: '',
processType: 'Validate',
excelData: ''
},
processResults: [],
importDialogVisible: false,
addDialogVisible: false
}
},
async mounted() {
await this.loadRules();
},
methods: {
async loadRules() {
const response = await this.$http.get('/api/regexrule/rules');
this.rules = response.data;
},
async exportRules() {
const response = await this.$http.get('/api/regexrule/export', {
responseType: 'blob'
});
// 下载文件
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', `正则规则_${new Date().toLocaleString()}.xlsx`);
document.body.appendChild(link);
link.click();
},
async processData() {
const dataRows = this.processForm.excelData.split('\n')
.filter(line => line.trim())
.map((line, index) => {
const parts = line.split(',');
return {
rowId: index + 1,
data: parts[0].trim(),
replacement: parts[1] ? parts[1].trim() : ''
};
});
const request = {
dataRows: dataRows,
ruleName: this.processForm.ruleName,
processType: this.processForm.processType
};
const response = await this.$http.post('/api/regexrule/process-excel', request);
this.processResults = response.data.results;
}
}
}
</script>
实际业务场景示例
场景1:电商订单处理
csharp
// 订单号验证规则:OD202312150001
"^OD\\d{12}$"
// 提取订单金额:"总金额:¥258.00" → "258.00"
"\\d+\\.\\d{2}"
场景2:日志分析
csharp
// 提取IP地址
"\\b(?:[0-9]{1,3}\\.){3}[0-9]{1,3}\\b"
// 提取错误时间戳
"\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}"
场景3:数据清洗
csharp
// 清理电话号码中的非数字字符
"[^0-9]"
// 统一日期格式
"(\\d{4})/(\\d{2})/(\\d{2})" → "$1-$2-$3"
这样的系统让业务人员可以:
- 通过Excel维护正则规则
- 批量验证数据格式
- 自动提取关键信息
- 标准化数据格式
- 查看处理日志和统计
大大提高了数据处理的效率和准确性!