正則表達式曾是熱門學習主題,本文整理筆記備忘,涵蓋語法、定位、重複、分組、貪婪/非貪婪、前瞻/後顧等核心概念。
C# 中 @ 表示後續字串為逐字字串,不處理逸出字元:
string x = "D:\\My Huang\\My Doc"; // 一般字串需雙反斜線
string y = @"D:\My Huang\My Doc"; // @字串可直接書寫
// 錯誤寫法:string z = "D:\My Huang\My Doc"; // \M、\D 視為逸出
正則表達式常搭配 @ 使用,避免雙重逸出混淆。
| 符號 | 說明 |
|---|---|
\d | 0-9 數字 |
\D | 非數字(\d 補集) |
\w | 單詞字元:字母、數字、底線 |
\W | 非單詞字元 |
\s | 空白字元:空格、\n、\r、\t、\v、\f |
\S | 非空白字元 |
. | 除換行符外任意字元 |
[...] | 字元集合,匹配括號內任一字元 |
[^...] | 排除字元集合 |
string i = "\n"; string m = "3";
Regex r = new Regex(@"\D");
r.IsMatch(i); // true
r.IsMatch(m); // false
string i = "%"; string m = "3";
Regex r = new Regex("[a-z0-9]");
r.IsMatch(i); // false
r.IsMatch(m); // true
| 符號 | 說明 |
|---|---|
^ | 字串開頭(多行模式下為行首) |
$ | 字串結尾(多行模式下為行尾) |
\b | 單詞邊界 |
\B | 非單詞邊界 |
\A | 字串絕對開頭 |
\z | 字串絕對結尾 |
\Z | 字串結尾或換行符前 |
string i = @"Live for nothing,
die for something";
Regex r1 = new Regex("^Live for nothing,die for something$"); // 0
Regex r2 = new Regex("^Live for nothing,die for something$", RegexOptions.Multiline); // 0
Regex r3 = new Regex("^Live for nothing,\r\ndie for something$"); // 1
Regex r9 = new Regex("^Live for nothing,\r$", RegexOptions.Multiline); // 1
Regex r11 = new Regex("^die for something$", RegexOptions.Multiline); // 1
| 符號 | 說明 |
|---|---|
{n} | 精確 n 次 |
{n,} | 至少 n 次 |
{n,m} | n 到 m 次 |
? | 0 或 1 次 |
+ | 1 次或以上 |
* | 0 次或以上 |
Regex r = new Regex(@"^\+?[1-9],?\d{3}$");
r.IsMatch("1024"); // true
r.IsMatch("+1024"); // true
r.IsMatch("1,024"); // true
r.IsMatch("1"); // false
r.IsMatch("-1024"); // false
r.IsMatch("10000"); // false
(...|...) 表示匹配左邊或右邊模式。[a-z] 也是擇一但僅限單字元。
Regex r = new Regex(@"^\+?((100(\.0+)*)|([1-9]?[0-9])(\.\d+)*)$");
r.IsMatch("0"); // true
r.IsMatch("0.23"); // true
r.IsMatch("100"); // true
r.IsMatch("100.01"); // false
r.IsMatch("9.9"); // true
r.IsMatch("99.9"); // true
r.IsMatch("99."); // false
r.IsMatch("00.1"); // false
// 匹配反斜線 \
string x = @"\";
new Regex(@"^\\$").IsMatch(x); // true
new Regex("^\\\\$").IsMatch(x); // true
// 匹配雙引號 "
string x = "\"";
new Regex("^\"$").IsMatch(x); // true
new Regex(@"^""$").IsMatch(x); // true
string x = "Live for nothing,die for something";
Regex r = new Regex(@"^Live ([a-z]{3}) no([a-z]{5}),die \1 some\2$");
r.IsMatch(x); // true
// 取得分組內容
Match m = r.Match(x);
m.Groups[1].Value; // "for"
m.Groups[2].Value; // "thing"
// 命名分組
Regex r = new Regex(@"^Live for no(?<g1>[a-z]{5}),die for some\1$");
m.Groups["g1"].Value; // "thing"
// 替換刪除重複單詞
string x = "Live for nothing nothing";
x = Regex.Replace(x, @"([a-z]+) \1", "$1"); // "Live for nothing"
x = Regex.Replace(x, @"(?<g1>[a-z]+) \1", "${g1}"); // 同上
(?:...)Regex r = new Regex(@"^Live for no(?:[a-z]{5})$");
r.Match(x).Groups[1].Value; // 空字串,不捕獲
預設貪婪(匹配越多越好),在量詞後加 ? 變非貪婪。
string x = "Live for nothing,die for something";
new Regex(@".*thing").Match(x).Value; // "Live for nothing,die for something"
new Regex(@".*?thing").Match(x).Value; // "Live for nothing"
(?>...) 強制非回溯(原子分組)。
string x = "Live for nothing,die for something";
new Regex(@".*thing,").Match(x).Value; // "Live for nothing," (回溯成功)
new Regex(@"(?>.*thing),").IsMatch(x); // false (非回溯失敗)
| 類型 | 語法 | 說明 |
|---|---|---|
| 正向前瞻 | (?=...) | 後方必須匹配...,不消耗字元 |
| 負向前瞻 | (?!...) | 後方不得匹配... |
| 正向後顧 | (?<=...) | 前方必須匹配...,不消耗字元 |
| 負向後顧 | (?<!...) | 前方不得匹配... |
// 正向前瞻:找後面跟 " used" 的 4 位數
string x = "1024 used 2048 free";
new Regex(@"\d{4}(?= used)").Match(x).Value; // "1024"
// 負向前瞻:找後面不跟 " used" 的 4 位數
new Regex(@"\d{4}(?! used)").Match(x).Value; // "2048"
// 正向後顧:找前面是 "used:" 的 4 位數
string x = "used:1024 free:2048";
new Regex(@"(?<=used:)\d{4}").Match(x).Value; // "1024"
// 負向後顧:找前面不是 "used:" 的 4 位數
new Regex(@"(?<!used:)\d{4}").Match(x).Value; // "2048"
\xXX:0-255 範圍字元(如空格 \x20)\uXXXX:任意 Unicode 字元(如中文 [\u4e00-\u9fa5])考慮:00、00.、00.00、001.100 合法;空字串、單獨 .、>100 不合法。
Regex r = new Regex(@"^\+?0*(?:100(\.0*)?|(\d{0,2}(?=\.\d)|\d{1,2}(?=($|\.$)))(\.\d*)?)$");
日期、URL、Email 精確匹配極難,建議依實際應用場景放寬要求(如限定常見格式、限定日期範圍)。