C# 正則表達式中雙引號的處理、分組引用、RegexOptions 枚舉、編譯優化、替換模式等核心知識點總結,結合實戰案例演示 CSS URL 提取、SQL 批量生成等場景。
在 C# 中處理包含雙引號的正則模式,有三種寫法:
| 方式 | 語法 | 示例 | 適用場景 |
|---|---|---|---|
| 逐字字符串 + 雙寫 | @"""" | @"""url\(""([^""]*)""\)"" | 最推薦,可讀性最好 |
| 普通字符串 + 轉義 | \" | \"url\\(\"([^\"]*)\"\\)\" | 需要換行符等轉義字符時 |
| 原始字符串字面量 | @$"" (C# 11+) | @$"url\(""([^""]*)""\)" | 現代語法,支持插值 |
// 目標:提取 url("...") 或 url('...') 中的路徑
// 正則:url\((['"]?)(.+?)\1\)
// C# 寫法:
var reg = new Regex(@"url\((['""]?)(.+?)\1\)");
// ↑ 逐字字符串
// ↑↑ 雙寫雙引號
// ↑ 單引號無需轉義
string css = @"background-image:url(""//ssl.gstatic.com/ui/v1/menu/checkmark.png"");";
var match = reg.Match(css);
Console.WriteLine(match.Value);
// 輸出:url("//ssl.gstatic.com/ui/v1/menu/checkmark.png")
Console.WriteLine(match.Groups[2].Value);
// 輸出://ssl.gstatic.com/ui/v1/menu/checkmark.png
// 命名分組語法:(?...)
// 反向引用:\k(注意:C# 用 k,非 \k)
var reg = new Regex(@"\b(?\w+)\s+\k\b");
string text = "what the hell are you you talking about?";
var match = reg.Match(text);
Console.WriteLine(match.Value); // "you you"
Console.WriteLine(match.Groups["word"].Value); // "you"
| 選項 | 說明 | 典型用途 |
|---|---|---|
Singleline | . 匹配任意字符(含換行) | 跨行匹配 HTML/JSON |
Multiline | ^$ 匹配行首行尾(非字符串首尾) | 多行文本逐行處理 |
IgnorePatternWhitespace | 忽略模式中的空白,允許註釋 # | 編寫可讀性強的複雜正則 |
IgnoreCase | 不區分大小寫匹配 | 關鍵字搜索、標簽匹配 |
ECMAScript | 限制 \w\d\s 僅匹配 ASCII | JS 兼容模式 |
RightToLeft | 從右向左匹配 | 特定解析場景 |
Compiled | 編譯為 IL,啟動慢但匹配快 | 高頻復用正則 |
ExplicitCapture | 普通括號 () 僅分組不捕獲 | 避免無意捕獲影響性能 |
CultureInvariant | 使用不變文化進行比較 | 跨文化一致性 |
| 指標 | 未編譯 | 已編譯 |
|---|---|---|
| 啟動速度 | 快 | 慢(最多 60 倍) |
| 內存佔用 | 少 | 多(每正則 5-15KB) |
| 匹配速度 | 基準 | 最多提升 10 倍 |
| 內存釋放 | 自動 | 進程結束前常駐 |
建議:僅對高頻復用、生命周期長的正則使用 Compiled;一次性或低頻正則不建議。
IgnoreCase、Multiline、Compiled 組合\10 僅為反向引用 1 + 字符 '0',非八進制\w\d\s 及其反向類僅匹配 ASCIIC# 正則分組編號順序:
// 示例:(\w)(?\d+)(\s+)
// 分組編號:
// 0: 整個匹配
// 1: (\w) - 未命名,第1個左括號
// 2: (\s+) - 未命名,第2個左括號
// 3: (?\d+) - 命名分組,最後編號
| 序列 | 替換內容 | 示例 |
|---|---|---|
$& / $0 | 整個匹配文本 | Regex.Replace("123", @"\d+", "[$&]") → "[123]" |
$1, $2... | 編號捕獲組文本 | Regex.Replace("1+1=3", @"1\+1=(\d)", "不是$1") → "不是3" |
${name} | 命名捕獲組文本 | Regex.Replace("1+1=3", @"1\+1=(? |
$` | 匹配文本之前的文本 | Regex.Replace("ABC123", @"\d+", "前:$`") → "前:ABCABC" |
$' | 匹配文本之後的文本 | Regex.Replace("123ABC", @"\d+", "後:$'") → "後:ABCABC" |
$$ | 字面量 $ | Regex.Replace("100", @"\d+", "價格:$$$&") → "價格:$100" |
$_ | 原始輸入字符串副本 | Regex.Replace("ABC123", @"\d+", $_) → "ABC123ABC123" |
$+ | 最後一個捕獲組文本 | .NET 特有 |
string keywords = File.ReadAllText(@"D:\daoru.txt", Encoding.Default);
// 關鍵詞每行一個,如:
// 中山大道
// 粵墾路
var reg = new Regex(@".+"); // 默認 . 不匹配換行,完美適配逐行
string sql = reg.Replace(keywords,
"INSERT INTO Keywords VALUES (196, 'admin', 'admin', '$&')");
// 處理換行符問題(關鍵!)
// Windows 換行 \r\n,匹配 .+ 會包含 \r
// 解決:替換後移除 \r
sql = sql.Replace("\r", "");
File.WriteAllText(@"D:\output.sql", sql);
// 生成:
// INSERT INTO Keywords VALUES (196, 'admin', 'admin', '中山大道')
// INSERT INTO Keywords VALUES (196, 'admin', 'admin', '粵墾路')
將常用正則預編譯為 DLL,提高重用性和啟動性能:
using System.Text.RegularExpressions;
var patterns = new[]
{
new RegexCompilationInfo(
@"\d{4}-\d{2}-\d{2}", // 模式
RegexOptions.Compiled | RegexOptions.ExplicitCapture, // 選項
"DateRegex", // 類名
"MyRegexLib", // 命名空間
true, // public
null // 超時
),
// 更多模式...
};
Regex.CompileToAssembly(patterns, new AssemblyName("MyRegexLib"));
// 生成 MyRegexLib.dll,其他項目引用即可使用:
// var regex = new MyRegexLib.DateRegex();
// regex.Match("2024-01-15");
@"""" 最不易出錯C# 正則表達式功能強大但細節多:雙引號轉義用逐字字符串雙寫,分組編號有序,替換模式豐富,編譯優化需權衡。掌握 RegexOptions 組合、命名分組、替換序列、預編譯組件化等進階技巧,能顯著提升文本處理代碼的性能、可讀性與維護性。