System.Text.RegularExpressions.Regex 類別
本文提供此 API 參考文件的補充備註。
類別 Regex 表示 。NET 的正則表示式引擎。 您可以使用這個類別來:
- 快速剖析大量的文字,以尋找特定的字元模式。
- 擷取、編輯、取代或刪除文字子字串。
- 將擷取的字串新增至集合以產生報表。
注意
如果您想要藉由判斷字串是否符合特定的正規表示式模式來驗證字串,您可以使用 類別 System.Configuration.RegexStringValidator 。
若要使用正規表示式,您可以使用正規表示式語言中所述的 語法來定義您想要在文字數據流中識別的模式 - 快速參考。 接下來,您可以選擇性地具現化 Regex 物件。 最後,您呼叫執行某些作業的方法,例如取代符合正則表達式模式的文字,或識別模式比對。
如需正則表示式語言的詳細資訊,請參閱 正則表達式語言 - 快速參考 或下載並列印下列其中一本摺頁冊:
Word 中的快速參考 (.docx) 格式PDF 快速參考 (.pdf) 格式
Regex 與 String 方法
類別 System.String 包含數個搜尋和比較方法,可用來執行與文字的模式比對。 例如,String.Contains、 String.EndsWith和 String.StartsWith 方法會判斷字串實例是否包含指定的子字串,而String.IndexOf、 String.LastIndexOfString.IndexOfAny和 String.LastIndexOfAny 方法會傳回字串中指定子字串的起始位置。 當您搜尋特定字串時,請使用 類別的方法 System.String 。 當您在字串中搜尋特定模式時,請使用 類別 Regex 。 如需詳細資訊和範例,請參閱 .NET 正則表達式。
靜態與實例方法
定義正規表示式模式之後,您可以使用下列兩種方式之一,將它提供給正則表達式引擎:
藉由具現化 Regex 代表正則表達式的物件。 若要這樣做,您會將正則表達式模式傳遞至建 Regex 構函式。 物件 Regex 是不可變的;當您具現 Regex 化具有正則表達式的物件時,就無法變更該物件的正則表達式。
藉由提供正則表達式和文字,以搜尋至
static
(Shared
在 Visual Basic 中) Regex 方法。 這可讓您使用正則表達式,而不需要明確建立 Regex 物件。
所有 Regex 模式識別方法都包含靜態和實例多載。
正則表達式引擎必須先編譯特定模式,才能使用模式。 因為 Regex 物件是不可變的,所以這是一 Regex 次性程式,會在呼叫類別建構函式或靜態方法時發生。 若要消除重複編譯單一正則表達式的需求,正則表達式引擎會快取靜態方法呼叫中使用的已編譯正則表達式。 因此,正則表達式模式比對方法會提供靜態和實例方法的可比較效能。 不過,在下列兩種情況下,快取可能會對效能造成負面影響:
當您搭配大量的正則表示式使用靜態方法呼叫時。 根據預設,正則表達式引擎會快取最近使用的15個靜態正則表示式。 如果您的應用程式使用超過15個靜態正則表示式,則必須重新編譯一些正則表達式。 若要防止此重新編譯,您可以增加 Regex.CacheSize 屬性。
當您使用先前編譯的正規表達式具現化新 Regex 物件時。 例如,下列程式代碼會定義正則表達式,以在文字數據流中尋找重複的字組。 雖然此範例使用單一正則表達式,但它會具現化新的 Regex 對象來處理每一行文字。 這會導致正則表達式與迴圈的每個反覆專案重新編譯。
StreamReader sr = new StreamReader(filename); string input; string pattern = @"\b(\w+)\s\1\b"; while (sr.Peek() >= 0) { input = sr.ReadLine(); Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase); MatchCollection matches = rgx.Matches(input); if (matches.Count > 0) { Console.WriteLine("{0} ({1} matches):", input, matches.Count); foreach (Match match in matches) Console.WriteLine(" " + match.Value); } } sr.Close();
Dim sr As New StreamReader(filename) Dim input As String Dim pattern As String = "\b(\w+)\s\1\b" Do While sr.Peek() >= 0 input = sr.ReadLine() Dim rgx As New Regex(pattern, RegexOptions.IgnoreCase) Dim matches As MatchCollection = rgx.Matches(input) If matches.Count > 0 Then Console.WriteLine("{0} ({1} matches):", input, matches.Count) For Each match As Match In matches Console.WriteLine(" " + match.Value) Next End If Loop sr.Close()
若要防止重新編譯,您應該具現化可供所有需要它的程式代碼存取的單 Regex 一物件,如下列重寫範例所示。
StreamReader sr = new StreamReader(filename); string input; string pattern = @"\b(\w+)\s\1\b"; Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase); while (sr.Peek() >= 0) { input = sr.ReadLine(); MatchCollection matches = rgx.Matches(input); if (matches.Count > 0) { Console.WriteLine("{0} ({1} matches):", input, matches.Count); foreach (Match match in matches) Console.WriteLine(" " + match.Value); } } sr.Close();
Dim sr As New StreamReader(filename) Dim input As String Dim pattern As String = "\b(\w+)\s\1\b" Dim rgx As New Regex(pattern, RegexOptions.IgnoreCase) Do While sr.Peek() >= 0 input = sr.ReadLine() Dim matches As MatchCollection = rgx.Matches(input) If matches.Count > 0 Then Console.WriteLine("{0} ({1} matches):", input, matches.Count) For Each match As Match In matches Console.WriteLine(" " + match.Value) Next End If Loop sr.Close()
執行正則表達式作業
不論您決定具現化 Regex 物件並呼叫其方法或呼叫靜態方法,類別 Regex 都提供下列模式比對功能:
比對的驗證。 您可以呼叫 IsMatch 方法來判斷相符專案是否存在。
擷取單一相符專案。 您可以呼叫 Match 方法來擷取 Match 物件,此物件代表字串或字串中的第一個相符專案。 藉由呼叫 Match.NextMatch 方法,即可擷取後續的相符專案。
擷取所有相符專案。 您可以呼叫 Matches 方法來擷取 System.Text.RegularExpressions.MatchCollection 物件,此物件代表字串或字串部分中找到的所有相符專案。
取代相符的文字。 您可以呼叫 Replace 方法來取代相符的文字。 取代文字也可以由正則表達式定義。 此外,某些 Replace 方法包含 MatchEvaluator 參數,可讓您以程序設計方式定義取代文字。
建立由輸入字串部分組成的字串陣列。 您可以呼叫 Split 方法來分割正則表示式所定義位置的輸入字串。
除了其模式比對方法之外,類別 Regex 還包含數個特殊用途的方法:
- 方法 Escape 會逸出任何可在正則表達式或輸入字串中解譯為正則表達式運算符的字元。
- 方法 Unescape 會移除這些逸出字元。
- 方法 CompileToAssembly 會建立包含預先定義正則表達式的元件。 .NET 包含命名空間中 System.Web.RegularExpressions 這些特殊用途元件的範例。
定義逾時值
.NET 支援功能完整的正則表達式語言,可在模式比對中提供大量強大功能和彈性。 不過,電源和彈性會付出代價:效能不佳的風險。 執行不佳的正則表示式很容易建立。 在某些情況下,依賴過度回溯的正則表達式作業在處理幾乎符合正則表示式模式的文字時,可能會停止回應。 如需 .NET 正則表達式引擎的詳細資訊,請參閱 正則表示式行為的詳細數據。 如需過度回溯的詳細資訊,請參閱 回溯。
從 .NET Framework 4.5 開始,您可以定義正則表達式相符專案的超時時間間隔,以限制過度回溯。 視正則表示式模式和輸入文字而定,運行時間可能會超過指定的逾時間隔,但不會花費比指定的超時時間間隔更多的時間回溯。 如果正則表達式引擎逾時,則會擲回 RegexMatchTimeoutException 例外狀況。 在大部分情況下,這可防止正則表達式引擎藉由嘗試比對幾乎符合正則表達式模式的文字來浪費處理能力。 不過,也可能表示逾時間隔已設定太低,或目前的機器負載導致效能整體降低。
處理例外狀況的方式取決於例外狀況的原因。 如果例外狀況是因為逾時間隔設定太低或因為機器負載過大,您可以增加超時時間間隔,然後重試比對作業。 如果因為正則表示式依賴過度回溯而發生例外狀況,您可以假設相符專案不存在,而且您可以選擇性地記錄可協助您修改正則表達式模式的資訊。
您可以藉由在具現化正則表達式物件時呼叫建構函式來 Regex(String, RegexOptions, TimeSpan) 設定超時時間間隔。 針對靜態方法,您可以呼叫具有 matchTimeout
參數的比對方法多載來設定超時時間間隔。 如果您未明確設定逾時值,則會決定預設逾時值,如下所示:
- 使用整個應用程式的逾時值 (如果有的話)。 呼叫 AppDomain.SetData 方法,將值的字串表示 TimeSpan 指派給
REGEX_DEFAULT_MATCH_TIMEOUT
屬性,以設定整個應用程式的逾時值。 - 果未設定整個應用程式的逾時值,則使用值 InfiniteMatchTimeout。
重要
建議您在所有正則表示式模式比對作業中設定逾時值。 如需詳細資訊,請參閱 正則表達式的最佳做法。
範例
下列範例會使用正則表達式來檢查字串中重複出現的單字。 正則表達式 \b(?<word>\w+)\s+(\k<word>)\b
可以解譯,如下表所示。
模式 | 描述 |
---|---|
\b |
在字邊界開始比對。 |
(?<word>\w+) |
比對一或多個字字元到字邊界。 將此擷取的群組 word 命名為 。 |
\s+ |
比對一個或多個空白字元。 |
(\k<word>) |
比對名為 word 的擷取群組。 |
\b |
比對字邊界。 |
using System;
using System.Text.RegularExpressions;
public class Test
{
public static void Main ()
{
// Define a regular expression for repeated words.
Regex rx = new Regex(@"\b(?<word>\w+)\s+(\k<word>)\b",
RegexOptions.Compiled | RegexOptions.IgnoreCase);
// Define a test string.
string text = "The the quick brown fox fox jumps over the lazy dog dog.";
// Find matches.
MatchCollection matches = rx.Matches(text);
// Report the number of matches found.
Console.WriteLine("{0} matches found in:\n {1}",
matches.Count,
text);
// Report on each match.
foreach (Match match in matches)
{
GroupCollection groups = match.Groups;
Console.WriteLine("'{0}' repeated at positions {1} and {2}",
groups["word"].Value,
groups[0].Index,
groups[1].Index);
}
}
}
// The example produces the following output to the console:
// 3 matches found in:
// The the quick brown fox fox jumps over the lazy dog dog.
// 'The' repeated at positions 0 and 4
// 'fox' repeated at positions 20 and 25
// 'dog' repeated at positions 49 and 53
Imports System.Text.RegularExpressions
Public Module Test
Public Sub Main()
' Define a regular expression for repeated words.
Dim rx As New Regex("\b(?<word>\w+)\s+(\k<word>)\b", _
RegexOptions.Compiled Or RegexOptions.IgnoreCase)
' Define a test string.
Dim text As String = "The the quick brown fox fox jumps over the lazy dog dog."
' Find matches.
Dim matches As MatchCollection = rx.Matches(text)
' Report the number of matches found.
Console.WriteLine("{0} matches found in:", matches.Count)
Console.WriteLine(" {0}", text)
' Report on each match.
For Each match As Match In matches
Dim groups As GroupCollection = match.Groups
Console.WriteLine("'{0}' repeated at positions {1} and {2}", _
groups.Item("word").Value, _
groups.Item(0).Index, _
groups.Item(1).Index)
Next
End Sub
End Module
' The example produces the following output to the console:
' 3 matches found in:
' The the quick brown fox fox jumps over the lazy dog dog.
' 'The' repeated at positions 0 and 4
' 'fox' repeated at positions 20 and 25
' 'dog' repeated at positions 49 and 53
下一個範例說明使用正則表達式來檢查字串是否代表貨幣值,或具有正確的格式來表示貨幣值。 在此情況下,正則表示式是從 en-US 文化特性的 NumberFormatInfo.CurrencyDecimalSeparator、 CurrencyDecimalDigits、 NumberFormatInfo.CurrencySymbolNumberFormatInfo.NegativeSign、 和 NumberFormatInfo.PositiveSign 屬性動態建置。 產生的正規表示式為 ^\s*[\+-]?\s?\$?\s?(\d*\.?\d{2}?){1}$
。 此正則表達式可以解譯,如下表所示。
模式 | 描述 |
---|---|
^ |
從字串開頭開始。 |
\s* |
比對零個以上的空白字元。 |
[\+-]? |
比對零或一次出現正負號或負號。 |
\s? |
比對零個或一個空白字元。 |
\$? |
比對零或一次出現貨幣符號。 |
\s? |
比對零個或一個空白字元。 |
\d* |
比對零個或多個十進位數字。 |
\.? |
比對零或一個小數點符號。 |
(\d{2})? |
擷取群組 1:比對兩個十進位數零或一次。 |
(\d*\.?(\d{2})?){1} |
比對以小數點符號完全分隔的整數和小數位數模式。 |
$ |
比對字串的結尾。 |
在此情況下,正則表示式會假設有效的貨幣字串不包含群組分隔符符號,而且其沒有小數位數或指定文化特性 CurrencyDecimalDigits 的 屬性所定義的小數位數。
using System;
using System.Globalization;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
// Get the en-US NumberFormatInfo object to build the regular
// expression pattern dynamically.
NumberFormatInfo nfi = CultureInfo.GetCultureInfo("en-US").NumberFormat;
// Define the regular expression pattern.
string pattern;
pattern = @"^\s*[";
// Get the positive and negative sign symbols.
pattern += Regex.Escape(nfi.PositiveSign + nfi.NegativeSign) + @"]?\s?";
// Get the currency symbol.
pattern += Regex.Escape(nfi.CurrencySymbol) + @"?\s?";
// Add integral digits to the pattern.
pattern += @"(\d*";
// Add the decimal separator.
pattern += Regex.Escape(nfi.CurrencyDecimalSeparator) + "?";
// Add the fractional digits.
pattern += @"(\d{";
// Determine the number of fractional digits in currency values.
pattern += nfi.CurrencyDecimalDigits.ToString() + "})?){1}$";
Console.WriteLine($"Pattern is {pattern}\n");
Regex rgx = new Regex(pattern);
// Define some test strings.
string[] tests = { "-42", "19.99", "0.001", "100 USD",
".34", "0.34", "1,052.21", "$10.62",
"+1.43", "-$0.23" };
// Check each test string against the regular expression.
foreach (string test in tests)
{
if (rgx.IsMatch(test))
Console.WriteLine($"{test} is a currency value.");
else
Console.WriteLine($"{test} is not a currency value.");
}
}
}
// The example displays the following output:
// Pattern is ^\s*[\+-]?\s?\$?\s?(\d*\.?(\d{2})?){1}$
//
// -42 is a currency value.
// 19.99 is a currency value.
// 0.001 is not a currency value.
// 100 USD is not a currency value.
// .34 is a currency value.
// 0.34 is a currency value.
// 1,052.21 is not a currency value.
// $10.62 is a currency value.
// +1.43 is a currency value.
// -$0.23 is a currency value.
Imports System.Globalization
Imports System.Text.RegularExpressions
Public Module Example
Public Sub Main()
' Get the current NumberFormatInfo object to build the regular
' expression pattern dynamically.
Dim nfi As NumberFormatInfo = CultureInfo.GetCultureInfo("en-US").NumberFormat
' Define the regular expression pattern.
Dim pattern As String
pattern = "^\s*["
' Get the positive and negative sign symbols.
pattern += Regex.Escape(nfi.PositiveSign + nfi.NegativeSign) + "]?\s?"
' Get the currency symbol.
pattern += Regex.Escape(nfi.CurrencySymbol) + "?\s?"
' Add integral digits to the pattern.
pattern += "(\d*"
' Add the decimal separator.
pattern += Regex.Escape(nfi.CurrencyDecimalSeparator) + "?"
' Add the fractional digits.
pattern += "(\d{"
' Determine the number of fractional digits in currency values.
pattern += nfi.CurrencyDecimalDigits.ToString() + "})?){1}$"
Console.WriteLine("Pattern is {0}", pattern)
Console.WriteLine()
Dim rgx As New Regex(pattern)
' Define some test strings.
Dim tests() As String = {"-42", "19.99", "0.001", "100 USD", _
".34", "0.34", "1,052.21", "$10.62", _
"+1.43", "-$0.23" }
' Check each test string against the regular expression.
For Each test As String In tests
If rgx.IsMatch(test) Then
Console.WriteLine("{0} is a currency value.", test)
Else
Console.WriteLine("{0} is not a currency value.", test)
End If
Next
End Sub
End Module
' The example displays the following output:
' Pattern is ^\s*[\+-]?\s?\$?\s?(\d*\.?(\d{2})?){1}$
'
' -42 is a currency value.
' 19.99 is a currency value.
' 0.001 is not a currency value.
' 100 USD is not a currency value.
' .34 is a currency value.
' 0.34 is a currency value.
' 1,052.21 is not a currency value.
' $10.62 is a currency value.
' +1.43 is a currency value.
' -$0.23 is a currency value.
由於此範例中的正則表示式是以動態方式建置,因此在設計時間,您不知道指定文化特性的貨幣符號、十進位符號或正負號(在此範例中為 en-US)可能會被正則表達式引擎誤譯為正則表達式語言運算符。 為了防止任何錯誤解譯,此範例會將每個動態產生的字串傳遞至 Escape 方法。