文字處理是很頻繁的例行工作,Regular Expression 正是一個複雜,但有效率的文字處理技術。
RegExp簡單的觀念就是先建立一組 pattern 字串, 再用這組字串去和資料做筆對。
例如判斷字串中是否含有"abc",或者含有email,或者含有身份證格式的文字....
如何使用 RegExpression 進行比對
命名空間: System.Text.RegularExpressions
幾個主要類別與方法:
- Regex 類別 :Represents an immutable regular expression.
- Regex.IsMatch :在輸入的字串中,規則運算式是否有比對到符合的資料。
- Regex.Match :在輸入字串中,搜尋符合規則運算式的項目,並且將第一個相符項目當做單一 Match 物件傳回。
- Regex.Matchs :在輸入字串中,搜尋規則運算式的所有相符項目,並傳回所有成功的相符項目。
- Regex.Replace :在指定的輸入字串內,使用指定的取代字串來取代符合規則運算式模式的所有字串。
- Match 類別 :表示單一規則運算式 (Regular Expression) 比對的結果。
- Match.Groups :取得符合規則運算式的群組集合。
- Group 類別 :表示單一擷取群組的結果。
- MatchCollection 類別 :所有找到的成功比對的集合。
如何比對簡單文字
下面這個例子會對 data 進行比對,判斷 data 是否由5個數字組成
string pattern = "^\d{5}$"; //由5個數字組成,該5個數字是開頭,該5個數字是結尾
string data = "12335";
if (Regex.IsMatch(data,pattern))
Console.WriteLine("It is matched.");
else
Console.WriteLine("It is NOT matched");
| | 「^」:次方符號表示字串開始 "\d" :表示數字字元 "{5}":表示前面規則要連續五個 「$」:表示字串結尾 |
上例的一些小變化
| pattern | data | result |
|---|---|---|
| ^\d{5}$ | 12345 | match |
| ^\d{5}$ | abcd12345 | no match |
| ^\d{5}$ | 12345abcd12345 | no match |
| ^\d{5}.*\d{5}$ | 12345abcd12345 | match |
| \d{5}$ | abcd12345 | match |
| \d{5}$ | drop custom 12345 | match |
規則運算式的特定字元
下方列表是用來定義規則運算式的特定字元
與位置相關的比對,詳細資訊請參閱MSDN[錨點]
| 記號 | 說明 | 模式 | 符合項目 |
|---|---|---|---|
| ^ | 必須發生在字串開頭 | ^\d{3} | "901-333-" 中的 "901-" |
| $ | 必須發生在字串結尾 | -\d{3}$ | "-901-333" 中的 "-333" |
| \A | 比對必須發生在字串開頭(忽略多行)。 | \A\d{3 | "-901-333" 中的 "901" |
| \Z | 比對必須發生在字串結尾(忽略多行) | -\d{3}\Z | "-901-333" 中的 "-333" |
| \z | 比對必須發生在字串結尾(忽略多行) | -\d{3}\z | "-901-333" 中的 "-333" |
| \G | 比對必須發生在先前比對結束的位置。 | \G\(\d\) | "(1)(3)(5)[7](9)" 中的 "(1)"、"(3)"、"(5)" |
| \b | 比對必須發生在 \w (英數) 和 \W (非英數) 字元之間的界限上。 | \b\w+\s\w+\b | "them theme them them" 中的 "them them" |
| \B | 比對不可以發生在 \b 界限上。 | \Bend\w*\b | "end sends endure lender" 中的 "ends"、"ender" |
與文字相關的比對,詳細資訊請參閱MSDN[字元類別]
| 記號 | 說明 | 模式 | 符合項目 |
|---|---|---|---|
| . | 萬用字元 | 代表除了換行符號 (\n) 以外的任一字元。如果要包括換行符號,請使用 [\s\S] | |
| x|y | 代表「或」 | 例如 (Sun|Mon|Tue|Wed|Thu|Fri|Sat), (日|一|二|三|四|五|六) ; 必須以左右括號括住 | |
| [xyz] | 比對[]中的任何單一字元。 | [abc] | "gray" 中的 "a" "lane" 中的 "a"、"e" |
| [a-z] | 比對[]中的字元範圍 | [A-Z] | "AB123" 中的 "A"、"B" |
| [^xyz} | 否定字元 | [^aei] | "reign" 中的 "r"、"g"、"n" |
| \p{name} | 符合 name 所指定類別名稱或區塊名稱之所有字元 | \p{Lu} \p{IsCyrillic} | "City Lights" 中的 "C"、"L"(找大寫類別文字) "ДЖem" 中的 "Д"、"Ж"(找IsCyrillic區塊文字) |
| \P{name} | 不符合 name 所指定類別名稱或區塊名稱之所有字元 | \P{Lu} \P{IsCyrillic} | "City" 中的 "i"、"t"、"y"(找非大寫類別文字) "ДЖem" 中的 "e"、"m"(找非IsCyrillic區塊文字) |
| \w | 比對任何文字字元, 相等於[A-Za-z0-9_]。 | \w | "ID A1.3" 中的 "I"、"D"、"A"、"1"、"3" |
| \W | 比對任何非文字字元, 相等於[^A-Za-z0-9_]。 | \W | "ID A1.3" 中的 " "、"." |
| \s | 比對任何泛空白字元。(包含空白、Tab、換頁符號), 相等於[\f\n\r\t\v]。 | \w\s | "ID A1.3" 中的 "D " |
| \S | 比對任何非泛空白字元, 相等於[^\f\n\r\t\v]。 | \s\S | |
| \d | 比對任何十進位數字。 | \d | |
| \D | 比對不是十進位數字的任何字元。 | \D |
與文字數量相關的比對,詳細資訊請參閱MSDN[數量詞]
| Greedy記號 | Lazy記號 | 說明 | 範例 | |||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| * | *? | 零次or多次 | 91* :9後面接零或多個1 | |||||||||||||||||||||||
| + | +? | 一次or多次 + 數量詞會比對前置項目一次或多次。它就相當於 {1,}。 | 比對開頭字母為 a ,接著一個或多個字母 n ,再接文字字元
| |||||||||||||||||||||||
| ? | ?? | 零次or一次 | ||||||||||||||||||||||||
| {n} | {n}? | n是一個非負整數,比對正好n次。 | 比對至少 3 個字組字元,但盡可能減少次數,後接點或句號字元。
| |||||||||||||||||||||||
| {n,} | {n,}? | n是一個非負整數,比對至少出現n次 | ||||||||||||||||||||||||
| {n,m} | {n,m}? | m,n均為非負整數,n<=m,比對至少出現n次,至多出現m次 | ||||||||||||||||||||||||
| 將 ? 字元附加至限定詞之後,則使用非貪婪式(nongreedy pattern matching) 也就是找最短的符合結果。 | 例如在字串"oooo"中, 若 pattern = "o+?" ,則符合的結果是 "o" 若 pattern = "o+" ,則符合的結果是 "oooo" | |||||||||||||||||||||||||
規則運算式的子運算式,詳細資訊請參閱MSDN[群組建構]
| 記號 | 說明 | 模式 | 符合項目 |
|---|---|---|---|
| (...) | 擷取符合的子運算式,並指派以零為起始的序號給它。 | (\w)\1 | "deep" 中的 "ee" |
| (?<name>...) | 將符合的子運算式擷取到具名群組中。 | (?<city>.*$) |
如何擷取比對資訊
除了比對某個字串是否與pattern相符之外,Regexp也可以把符合的資訊擷取出來。
1.只取得第一個符合的字串 ( Regex.Match )
string pattern = @"Company Name: (.*$)"; string data = @" Company Name: Contoso, Inc. Company Name: Fis Inc. Company Name: china time newspaper"; Regex r1 = new Regex(pattern, RegexOptions.Multiline); Match m1 = r1.Match(data); Console.WriteLine(m1.Groups[1]); //======output:====== //Contoso, Inc.
2.逐步比對,取出所有符合的字串 ( Match.NextMatch )
//2.逐步比對,取出所有符合的字串
Regex r2 = new Regex(pattern, RegexOptions.Multiline);
Match m2;
for (m2 = r2.Match(data); m2.Success; m2 = m2.NextMatch())
{
Console.WriteLine("Found '{0}' at position {1}", m2.Groups[1], m2.Groups[1].Index);
}
//======output:======
//Found 'Contoso, Inc.' at position 28
//Found 'Fis Inc.' at position 69
//Found 'china time newspaper' at position 105
3.一次比對,取出所有符合的字串 ( Regex.Matchs )
Regex r3 = new Regex(@"Company Name: (.*$)", RegexOptions.Multiline);
MatchCollection matches = r2.Matches(inputString);
foreach (Match m3 in matches)
{
Console.WriteLine("Found '{0}' at position {1}", m3.Value, m3.Index);
}
//======output:======
//Found 'Company Name: Contoso, Inc.' at position 14
//Found 'Contoso, Inc.' at position 28
//Found 'Company Name: Fis Inc.' at position 55
//Found 'Fis Inc.' at position 69
//Found 'Company Name: china time newspaper' at position 91
//Found 'china time newspaper' at position 105
4.子運算式的比對,使用群組擷取符合的字串 ( Match.Groups )
規則運算式模式可以包含子運算式,子運算式是以括號括住的部分,每個子運算式都形成一個群組。
例如,pattern ="(\d{3})-(\d{3}-\d{4})" 會比對北美地區的電話號碼,其中包含兩個子運算式。
第一個子運算式「(\d{3})」代表區碼,第二個子運算式「 (\d{3}-\d{4})」代表電話號碼,
接著可從 Groups 屬性傳回的 GroupCollection 物件擷取這兩個群組,如下列範例所示。
string pattern = @"(\d{3})-(\d{3}-\d{4})";
string input = "212-555-6666 906-932-a111 415-222-3333 425-888-999";
MatchCollection matches = Regex.Matches(input, pattern);
foreach (Match match in matches)
{
Console.WriteLine("Area Code: {0}", match.Groups[1].Value);
Console.WriteLine("Telephone number: {0}", match.Groups[2].Value);
}
//output:
//match.Groups[0]: 212-555-6666
//Area Code: 212
//Telephone number: 555-6666
//match.Groups[0]: 415-222-3333
//Area Code: 415
//Telephone number: 222-3333
5.使用具名群組擷取字串 ( Match.Groups )
string pattern = @"First Name : (?<firstname>.*$)\n" +
@"Last Name : (?<lastname>.*$)\n" +
@"Age : (?<age>.*$)\n" +
@"City : (?<city>.*$)";
string data = @"First Name : Vito
Last Name : Shao
Age : 18
City : Taipei
";
Match m = Regex.Match(data, pattern, RegexOptions.Multiline);
if (m.Success)
{
Console.WriteLine("firstName:{0}", m.Groups["firstname"]);
Console.WriteLine("lastName:{0}", m.Groups["lastname"]);
Console.WriteLine("city:{0}", m.Groups["city"]);
Console.WriteLine("age:{0}", m.Groups["age"]);
}
//======OUTPUT======
//firstName:Vito
//lastName:Shao
//city:Taipei
//age:18
如何使用 RegExpression 替換子字串
下面例子示範如何利用 Regex.Replace 方法
該運算式會比對一或多個空白字元,將結果以單一空白字元取代。
string input = "This is text with far too much " +
"whitespace.";
string pattern = "\\s+";
string replacement = " ";
Regex rgx = new Regex(pattern);
string result = rgx.Replace(input, replacement);
Console.WriteLine("Original String: {0}", input);
Console.WriteLine("Replacement String: {0}", result);
// The example displays the following output:
// Original String :This is text with far too much whitespace.
// Replacement String:This is text with far too much whitespace.
}範例說明
| 用途 | Pattern | 說明 |
|---|---|---|
| 身份證 | [A-Z][12](\d{8}) | |
| ^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,30}$ | 1aAxxxyyy | |
- MSDN 規則運算式語言項目
- 這個網站有很多現成的pattern可供參考
沒有留言:
張貼留言