在 Windows Form 中使用正規式 Regex 來解析字串

這邊先推薦大家一個很棒的網頁:RegExr: Learn, Build, & Test RegEx。除了可以快速驗證規則之外,底下附有詳細的解說,滑鼠移到表示式上還會用顏色做區分,另外左邊的側邊攔還有規則總整理,無論是學習、查詢規則、還是測試都相當方便。

許多地方都可以看見正規表示式的身影,驗證資料、字串取數值等。這篇不講正規表示式的規則以及寫法,只講述正規式在 Windows Form 中的使用方式。

尋找規則

利用Regex這個Class來製作一個正規表示式,就可以利用 Match 以及 Matches 這兩個方法來找到我們想要找到的東西。

Match

此方法只會回傳第一個找到的字串集,要找到多個請用 Matches。為求簡便,示範中使用相當簡單的正規式規則。在 C# 中使用@前綴字元表示後面的字串是正規表達式。

string pattern = @"old (day)";
string input = "An extraordinary old day dawns with each new day.";
Match m = Regex.Match(input, pattern, RegexOptions.IgnoreCase);

// m.Value = "old day"
//
// m.Groups[0].Value = "old day"
// m.Groups[1].Value = "day" 

如果你是使用 C++/CLI,Match 的行為我直接整理在下一段。

Matches

如果一次要找到全部,使用 Matches 會回傳 MatchCollection,再使用簡單的 foreach 迴圈就可以把全部都找到。

string pattern = @"\b(\w*)\b day";
string input = "An extraordinary old day dawns with each new day.";
MatchCollection ms = Regex.Matches(input, pattern, RegexOptions.IgnoreCase);
foreach(Match m in ms)
{
  /*
   * First Match m is
   */
  // m.Value = "old day"
  //
  // m.Groups[0].Value = "old day"
  // m.Groups[1].Value = "old"

  /*
   * Second Match m is
   */
  // m.Value = "new day"
  //
  // m.Groups[0].Value = "new day"
  // m.Groups[1].Value = "new"
} 

在 C++/CLI中,Match 就會幫你找到全部,而其歷遍的方式有點不太一樣。

using namespace System;
using namespace System::Text::RegularExpressions;

Regex^ regex = gcnew Regex("\\b(?<word>\\w*)\\b day");
String^ input = "An extraordinary old day dawns with each new day.";

for (Match^ m = regex->Match(input); m->Success; m = m->NextMatch()) {
    /*
     * First Match m is
     */
    // m->Value = "old day"
    // m->Groups["word"] = "old"
    /*
     * Second Match m is
     */
    // m->Value = "new day"
    // m->Groups["word"] = "new"
} 

記得在前面補上對應的 namespace,並且記得在創建正規表達式的時候,我們需要多寫一個反斜線\來跳脫反斜線(有點麻煩)。在捕捉關鍵字的地方,也就是左右小刮號包起來之處,還需要設定一個用來取值的 key,例子中我設定為 word,所以就可以在歷遍時以 m->Groups["word"]這樣的方式來取得搜尋的值。

取代

Replace

此方法會將字串中所有符合規則的字串都以所指定的新字串來取代掉。

string pattern = @"\b(\w*)\b day";
string input = "An extraordinary old day dawns with each new day.";

string result  = Regex.Replace(input, pattern, "SUN", RegexOptions.IgnoreCase | RegexOptions.Multiline);
// result = "An extraordinary SUN dawns with each SUN." 

C++/CLI 的版本:

String^ pattern = "\\b(?<word>\\w*)\\b day";
String^ input = "An extraordinary old day dawns with each new day.";

String^ result = Regex::Replace(path, pattern, "SUN", RegexOptions::IgnoreCase | RegexOptions::Multiline);
// result = "An extraordinary SUN dawns with each SUN." 

References

  1. RegExr: Learn, Build, & Test RegEx
  2. Regex Class (System.Text.RegularExpressions) | Microsoft Docs