共用方式為


規則運算式中的數量詞

數量詞指定輸入中要有多少字元、群組或字元類別的出現次數,才能找到相符項目。 下表列出 .NET 支援的數量詞:

貪婪數量詞 懶惰數量詞 描述
* *? 匹配零次或多次。
+ +? 比對一或多次。
? ?? 匹配零次或一次。
{ n} { n}? 恰好匹配 n 次。
{ n,} { n,}? 至少匹配 n 次。
{ n,m} { n,m}? 比對 nm 次。

數量 nm 都是整數常數。 一般而言,數量詞是貪婪的。 它會使正則表達式引擎儘可能匹配特定模式的多次出現。 將 ? 字元附加至數量詞會使其延遲。 會導致規則運算式引擎盡可能比對最少的出現次數。 如需 Greedy (窮盡) 與 Lazy (最少) 數量詞差異的完整說明,請參閱本文稍後的 Greedy (窮盡) 與 Lazy (最少) 數量詞一節。

重要

巢狀數量詞,例如規則運算式模式 (a*)*,會增加規則運算式引擎需要執行的比較次數。 輸入字串中的字元數目越多,比較數量可能會呈指數增長。 如需此行為與其因應措施的詳細資訊,請參閱回溯

規則運算式量詞

下列章節會列出 .NET 規則運算式支援的數量詞:

注意

如果規則運算式模式中同時出現 *、+、?、{ 和 } 字元,除非它們包含在字元類別中,否則,規則運算式引擎會將它們解譯為數量詞或數量詞建構的一部分。 若要在字元類別外將這些字元解讀為字面字元,您必須在它們前面加上反斜線以跳脫字元。 例如,字串 \* 在規則運算式模式中會解譯成字面星號 ("*") 字元。

匹配零次或多次:*

* 數量詞會匹配前面的元素零次或多次。 相當於 {0,} 數量詞。 * 是一個貪婪 (Greedy) 數量詞,其對應的懶惰 (Lazy) 數量詞是 *?

以下示例說明此正則表示式。 在輸入字串的九個數字中,有五個符合模式,四個 (9592992199919) 不符合。

string pattern = @"\b91*9*\b";
string input = "99 95 919 929 9119 9219 999 9919 91119";
foreach (Match match in Regex.Matches(input, pattern))
   Console.WriteLine($"'{match.Value}' found at position {match.Index}.");

// The example displays the following output:
//       '99' found at position 0.
//       '919' found at position 6.
//       '9119' found at position 14.
//       '999' found at position 24.
//       '91119' found at position 33.
Dim pattern As String = "\b91*9*\b"
Dim input As String = "99 95 919 929 9119 9219 999 9919 91119"
For Each match As Match In Regex.Matches(input, pattern)
    Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
'       '99' found at position 0.
'       '919' found at position 6.
'       '9119' found at position 14.
'       '999' found at position 24.
'       '91119' found at position 33.

規則運算式模式的定義如下表所示:

模式 描述
\b 指定比對必須從字邊界開始。
91* 比對 9 後接著零或多個 1 字元。
9* 比對零或多個 9 字元。
\b 指定比對必須以字邊界結尾。

比對一或多次:+

+ 數量詞會比對前置元素一或多次。 相當於 {1,}+ 是一個貪婪 (Greedy) 數量詞,其對應的懶惰 (Lazy) 數量詞是 +?

例如,規則運算式 \ban+\w*?\b 會嘗試比對以字母 a 開頭、接著一或多個字母 n 的單字。 以下示例說明此正則表示式。 規則運算式會比對出單字 anannualannouncementantique,而不會比對出 autumnall

string pattern = @"\ban+\w*?\b";

string input = "Autumn is a great time for an annual announcement to all antique collectors.";
foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
   Console.WriteLine($"'{match.Value}' found at position {match.Index}.");

// The example displays the following output:
//       'an' found at position 27.
//       'annual' found at position 30.
//       'announcement' found at position 37.
//       'antique' found at position 57.
Dim pattern As String = "\ban+\w*?\b"

Dim input As String = "Autumn is a great time for an annual announcement to all antique collectors."
For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
    Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
'       'an' found at position 27.
'       'annual' found at position 30.
'       'announcement' found at position 37.
'       'antique' found at position 57.

規則運算式模式的定義如下表所示:

模式 描述
\b 從字的邊界開始。
an+ 比對一個 a,後面接著一個或多個 n 字元。
\w*? 比對單字字元零或多次,但次數愈少愈好。
\b 在字邊界結束。

比對零或一次:?

? 數量詞會比對前置元素零或一次。 相當於 {0,1}? 是一個貪婪 (Greedy) 數量詞,其對應的懶惰 (Lazy) 數量詞是 ??

例如,規則運算式 \ban?\b 會嘗試比對以字母 a 開頭且後面接著零個或一個字母 n 出現的整個單詞。 換言之,它會嘗試比對單字 aan。 以下範例說明此規則運算式:

string pattern = @"\ban?\b";
string input = "An amiable animal with a large snout and an animated nose.";
foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
   Console.WriteLine($"'{match.Value}' found at position {match.Index}.");

// The example displays the following output:
//        'An' found at position 0.
//        'a' found at position 23.
//        'an' found at position 42.
Dim pattern As String = "\ban?\b"
Dim input As String = "An amiable animal with a large snout and an animated nose."
For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
    Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
'       'An' found at position 0.
'       'a' found at position 23.
'       'an' found at position 42.

規則運算式模式的定義如下表所示:

模式 描述
\b 從字的邊界開始。
an? 比對a後面接著零個或一個n字元。
\b 在字邊界結束。

精確比對 n 次:{n}

{ n} 數量詞會精確匹配前面的元素 n 次,其中 n 是任何整數。 { n} 是貪婪數量詞,其相應的最小化形式是 {n}?

例如,正規表示式 \b\d+\,\d{3}\b 會嘗試比對一個字邊界,然後是一個或多個十進位數字,接著是三個十進位數字,最後再是一個字邊界。 以下範例說明此規則運算式:

string pattern = @"\b\d+\,\d{3}\b";
string input = "Sales totaled 103,524 million in January, " +
                      "106,971 million in February, but only " +
                      "943 million in March.";
foreach (Match match in Regex.Matches(input, pattern))
   Console.WriteLine($"'{match.Value}' found at position {match.Index}.");

//  The example displays the following output:
//        '103,524' found at position 14.
//        '106,971' found at position 45.
Dim pattern As String = "\b\d+\,\d{3}\b"
Dim input As String = "Sales totaled 103,524 million in January, " + _
                      "106,971 million in February, but only " + _
                      "943 million in March."
For Each match As Match In Regex.Matches(input, pattern)
    Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
'       '103,524' found at position 14.
'       '106,971' found at position 45.

規則運算式模式的定義如下表所示:

模式 描述
\b 從字的邊界開始。
\d+ 比對一個或多個十進位數字。
\, 比對逗號字元。
\d{3} 比對三個十進位數字。
\b 在字邊界結束。

至少匹配 n 次:{n,}

{ n,} 數量詞至少會比對 n 次前置項目,其中 n 是任何整數。 { n,} 是貪婪數量詞,其相應的最小化形式是 {n,}?

例如,這個正則表達式 \b\d{2,}\b\D+ 嘗試匹配單詞邊界,接著至少兩個數字,再接單詞邊界,然後是一個非數字字元。 以下示例說明此正則表示式。 此規則運算式無法比對出片語 "7 days",因為其只包含一個十進位數字,但會成功比對出片語 "10 weeks""300 years"

string pattern = @"\b\d{2,}\b\D+";
string input = "7 days, 10 weeks, 300 years";
foreach (Match match in Regex.Matches(input, pattern))
   Console.WriteLine($"'{match.Value}' found at position {match.Index}.");

//  The example displays the following output:
//        '10 weeks, ' found at position 8.
//        '300 years' found at position 18.
Dim pattern As String = "\b\d{2,}\b\D+"
Dim input As String = "7 days, 10 weeks, 300 years"
For Each match As Match In Regex.Matches(input, pattern)
    Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
'       '10 weeks, ' found at position 8.
'       '300 years' found at position 18.

規則運算式模式的定義如下表所示:

模式 描述
\b 從字的邊界開始。
\d{2,} 至少比對兩個十進位數字。
\b 比對字邊界。
\D+ 至少比對一個非十進位數字。

匹配 n 至 m 次:{n,m}

{ n,m} 數量詞至少比對 n 次前置項目,但不超過 m 次,其中 nm 都是整數。 { n,m} 是一個貪婪數量詞,其相對應的懶惰數量詞是 {n,m}?

在下例中,正則運算式 (00\s){2,4} 會嘗試匹配含有兩個零後接空格的數組,並且出現 2 至 4 次。 輸入字串的最後部分包含這個模式共出現了五次,而非最多四次。 不過,只有這個子字串的初始部分(即到空格處以及第五對零之前)符合正則表達式模式。

string pattern = @"(00\s){2,4}";
string input = "0x00 FF 00 00 18 17 FF 00 00 00 21 00 00 00 00 00";
foreach (Match match in Regex.Matches(input, pattern))
   Console.WriteLine($"'{match.Value}' found at position {match.Index}.");

//  The example displays the following output:
//        '00 00 ' found at position 8.
//        '00 00 00 ' found at position 23.
//        '00 00 00 00 ' found at position 35.
Dim pattern As String = "(00\s){2,4}"
Dim input As String = "0x00 FF 00 00 18 17 FF 00 00 00 21 00 00 00 00 00"
For Each match As Match In Regex.Matches(input, pattern)
    Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
'       '00 00 ' found at position 8.
'       '00 00 00 ' found at position 23.
'       '00 00 00 00 ' found at position 35.

匹配零或多次(惰性匹配):*?

*? 數量詞會比對前置元素零或多次,但次數越少越好。 其為 Greedy (窮盡) 數量詞 * 的對應 Lazy (最少)。

在下例中,規則運算式 \b\w*?oo\w*?\b 會比對包含字串 oo 的所有文字。

 string pattern = @"\b\w*?oo\w*?\b";
 string input = "woof root root rob oof woo woe";
 foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
    Console.WriteLine($"'{match.Value}' found at position {match.Index}.");

 //  The example displays the following output:
//        'woof' found at position 0.
//        'root' found at position 5.
//        'root' found at position 10.
//        'oof' found at position 19.
//        'woo' found at position 23.
Dim pattern As String = "\b\w*?oo\w*?\b"
Dim input As String = "woof root root rob oof woo woe"
For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
    Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
'       'woof' found at position 0.
'       'root' found at position 5.
'       'root' found at position 10.
'       'oof' found at position 19.
'       'woo' found at position 23.

規則運算式模式的定義如下表所示:

模式 描述
\b 從字的邊界開始。
\w*? 匹配零或多個單詞字符,但儘可能匹配最少的字符。
oo 比對字串 oo
\w*? 匹配零或多個單詞字符,但儘可能匹配最少的字符。
\b 在詞語邊界結束。

比對一次或多次(懶惰比對):+?

+? 數量詞會比對前置元素一或多次,但次數越少越好。 其為 Greedy (窮盡) 數量詞 + 的對應 Lazy (最少)。

例如,規則運算式 \b\w+?\b 會比對一或多個以字邊界分隔的字元。 以下範例說明此規則運算式:

string pattern = @"\b\w+?\b";
string input = "Aa Bb Cc Dd Ee Ff";
foreach (Match match in Regex.Matches(input, pattern))
   Console.WriteLine($"'{match.Value}' found at position {match.Index}.");

//  The example displays the following output:
//        'Aa' found at position 0.
//        'Bb' found at position 3.
//        'Cc' found at position 6.
//        'Dd' found at position 9.
//        'Ee' found at position 12.
//        'Ff' found at position 15.
Dim pattern As String = "\b\w+?\b"
Dim input As String = "Aa Bb Cc Dd Ee Ff"
For Each match As Match In Regex.Matches(input, pattern)
    Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
'       'Aa' found at position 0.
'       'Bb' found at position 3.
'       'Cc' found at position 6.
'       'Dd' found at position 9.
'       'Ee' found at position 12.
'       'Ff' found at position 15.

比對零或一次 (懶惰匹配):??

?? 數量詞會比對前置元素零或一次,但次數越少越好。 其為 Greedy (窮盡) 數量詞 ? 的對應 Lazy (最少)。

例如,規則運算式 ^\s*(System.)??Console.Write(Line)??\(?? 會嘗試比對字串 Console.WriteConsole.WriteLine。 字串也可以在 System. 之前包含 Console,而且後面可以接著左括號。 字串必須位在行的開頭,雖然前面可以是空格。 以下範例說明此規則運算式:

string pattern = @"^\s*(System.)??Console.Write(Line)??\(??";
string input = "System.Console.WriteLine(\"Hello!\")\n" +
                      "Console.Write(\"Hello!\")\n" +
                      "Console.WriteLine(\"Hello!\")\n" +
                      "Console.ReadLine()\n" +
                      "   Console.WriteLine";
foreach (Match match in Regex.Matches(input, pattern,
                                      RegexOptions.IgnorePatternWhitespace |
                                      RegexOptions.IgnoreCase |
                                      RegexOptions.Multiline))
   Console.WriteLine($"'{match.Value}' found at position {match.Index}.");

//  The example displays the following output:
//        'System.Console.Write' found at position 0.
//        'Console.Write' found at position 36.
//        'Console.Write' found at position 61.
//        '   Console.Write' found at position 110.
Dim pattern As String = "^\s*(System.)??Console.Write(Line)??\(??"
Dim input As String = "System.Console.WriteLine(""Hello!"")" + vbCrLf + _
                      "Console.Write(""Hello!"")" + vbCrLf + _
                      "Console.WriteLine(""Hello!"")" + vbCrLf + _
                      "Console.ReadLine()" + vbCrLf + _
                      "   Console.WriteLine"
For Each match As Match In Regex.Matches(input, pattern, _
                                         RegexOptions.IgnorePatternWhitespace Or RegexOptions.IgnoreCase Or RegexOptions.MultiLine)
    Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
'       'System.Console.Write' found at position 0.
'       'Console.Write' found at position 36.
'       'Console.Write' found at position 61.
'       '   Console.Write' found at position 110.

規則運算式模式的定義如下表所示:

模式 描述
^ 比對輸入資料流的開頭。
\s* 可以比對零個或多個空白字元。
(System.)?? 符合出現零次或一次的字串 System.
Console.Write 比對字串 Console.Write
(Line)?? 符合出現零次或一次的字串 Line
\(?? 比對左括號出現零次或一次的情況。

精確比對 n 次(懶惰比對):{n}?

{ n}? 數量詞會將前置項目確實比對 n 次,n 是任何整數。 { n} 的懶惰數量詞,是貪婪數量詞的對應。

下例會使用規則運算式 \b(\w{3,}?\.){2}?\w{3,}?\b 來識別網址。 運算式會比對 www.microsoft.commsdn.microsoft.com,但是不會比對 mywebsitemycompany.com

string pattern = @"\b(\w{3,}?\.){2}?\w{3,}?\b";
string input = "www.microsoft.com msdn.microsoft.com mywebsite mycompany.com";
foreach (Match match in Regex.Matches(input, pattern))
   Console.WriteLine($"'{match.Value}' found at position {match.Index}.");

//  The example displays the following output:
//        'www.microsoft.com' found at position 0.
//        'msdn.microsoft.com' found at position 18.
Dim pattern As String = "\b(\w{3,}?\.){2}?\w{3,}?\b"
Dim input As String = "www.microsoft.com msdn.microsoft.com mywebsite mycompany.com"
For Each match As Match In Regex.Matches(input, pattern)
    Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
'       'www.microsoft.com' found at position 0.
'       'msdn.microsoft.com' found at position 18.

規則運算式模式的定義如下表所示:

模式 描述
\b 從字的邊界開始。
(\w{3,}?\.) 比對至少三個單字字元,但字元愈少愈好,後面接著點或句號字元。 這個模式是第一個擷取群組。
(\w{3,}?\.){2}? 比對兩次第一個群組中的模式,但次數愈少愈好。
\b 在字邊界結束匹配。

至少匹配 n 次(懶惰比對):{n,}?

{ n,}? 數量詞至少會比對 n 次前置項目,其中 n 是任何整數,但次數愈少愈好。 { n,} 的懶惰數量詞,是貪婪數量詞的對應。

如需說明,請參閱上一節中 {n}? 數量詞的範例。 在該例中,規則運算式使用 {n,} 數量詞來比對包含至少三個字元且後接句號的字串。

比對 n 到 m 次(非貪婪匹配):{n,m}?

{ n,m}? 數量詞會比對前置項目 nm 次,其中 nm 都是整數,但次數越少越好。 其為 Greedy (窮盡) 數量詞 {n,m} 的對應 Lazy (最少)。

在下例中,規則運算式 \b[A-Z](\w*?\s*?){1,10}[.!?] 會比對包含 1 到 10 個單字的句子。 它會比對輸入字串中的所有句子,除了包含 18 個字的句子。

string pattern = @"\b[A-Z](\w*?\s*?){1,10}[.!?]";
string input = "Hi. I am writing a short note. Its purpose is " +
                      "to test a regular expression that attempts to find " +
                      "sentences with ten or fewer words. Most sentences " +
                      "in this note are short.";
foreach (Match match in Regex.Matches(input, pattern))
   Console.WriteLine($"'{match.Value}' found at position {match.Index}.");

//  The example displays the following output:
//        'Hi.' found at position 0.
//        'I am writing a short note.' found at position 4.
//        'Most sentences in this note are short.' found at position 132.
Dim pattern As String = "\b[A-Z](\w*\s?){1,10}?[.!?]"
Dim input As String = "Hi. I am writing a short note. Its purpose is " + _
                      "to test a regular expression that attempts to find " + _
                      "sentences with ten or fewer words. Most sentences " + _
                      "in this note are short."
For Each match As Match In Regex.Matches(input, pattern)
    Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
'       'Hi.' found at position 0.
'       'I am writing a short note.' found at position 4.
'       'Most sentences in this note are short.' found at position 132.

規則運算式模式的定義如下表所示:

模式 描述
\b 從字的邊界開始。
[A-Z] 比對從 A 到 Z 的大寫字元。
(\w*?\s*?) 比對零個或多個文字字元,其後接著一個或多個空白字元,並盡可能少出現。 這個模式是第一個擷取群組。
{1,10} 比對 1 到 10 次上一個模式。
[.!?] 比對任一標點符號字元 .!?

Greedy (匹配優先) 與 Lazy (忽略優先) 量詞

某些數量詞有兩個版本:

  • 貪婪版本。

    貪婪數量詞會嘗試盡可能多次匹配元素。

  • 非貪婪(或懶惰)版本。

    非貪婪量詞會嘗試盡可能少匹配元素。 只要加上 ?,就可將貪婪數量詞變成懶惰數量詞。

請考慮旨在擷取數字字串末四碼的正規表達式,例如信用卡號碼。 使用 * 貪婪量詞的正規表示式版本為 \b.*([0-9]{4})\b。 但若字串包含兩組數字,這個規則運算式只會比對第二組數字的末四碼,如下列範例所示:

string greedyPattern = @"\b.*([0-9]{4})\b";
string input1 = "1112223333 3992991999";
foreach (Match match in Regex.Matches(input1, greedyPattern))
   Console.WriteLine($"Account ending in ******{match.Groups[1].Value}.");

// The example displays the following output:
//       Account ending in ******1999.
Dim greedyPattern As String = "\b.*([0-9]{4})\b"
Dim input1 As String = "1112223333 3992991999"
For Each match As Match In Regex.Matches(input1, greedypattern)
    Console.WriteLine("Account ending in ******{0}.", match.Groups(1).Value)
Next
' The example displays the following output:
'       Account ending in ******1999.

規則運算式無法比對第一組數字,因為 * 數量詞會在整個字串中盡可能多次嘗試比對上一個元素,所以會在字串結尾找到相符項目。

此行為不是所需的行為。 相反地,您可以使用 *? lazy 數量詞來從這兩個數字中擷取位數,如下例所示:

string lazyPattern = @"\b.*?([0-9]{4})\b";
string input2 = "1112223333 3992991999";
foreach (Match match in Regex.Matches(input2, lazyPattern))
   Console.WriteLine($"Account ending in ******{match.Groups[1].Value}.");

// The example displays the following output:
//       Account ending in ******3333.
//       Account ending in ******1999.
Dim lazyPattern As String = "\b.*?([0-9]{4})\b"
Dim input2 As String = "1112223333 3992991999"
For Each match As Match In Regex.Matches(input2, lazypattern)
    Console.WriteLine("Account ending in ******{0}.", match.Groups(1).Value)
Next
' The example displays the following output:
'       Account ending in ******3333.
'       Account ending in ******1999.

在大部分情況下,使用貪婪 (Greedy) 和懶惰 (Lazy) 數量詞的正則表達式會傳回相同的匹配。 當它們與萬用字元 (.) 中繼字元一起使用時,最常出現不同的結果,因為它可比對任何字元。

量詞和空匹配

當找到最小的比對次數時,數量詞 *+{n,m} 及其對應的惰性版本在空白比對之後從不重複。 當可能捕捉群組的最大數目是無限或接近無限時,此規則可防止量詞在匹配空子運算式時進入無限迴圈。

例如,下列程式碼顯示呼叫 Regex.Match 方法的結果,其中依照可以比對 (a?)* 字元零到多次的正規運算式模式 a 進行匹配。 單一擷取群組會擷取每個 a 以及 String.Empty,但不會有第二個空字串的比對,因為第一個空字串的比對就會導致量詞停止重複。

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = "(a?)*";
      string input = "aaabbb";
      Match match = Regex.Match(input, pattern);
      Console.WriteLine($"Match: '{match.Value}' at index {match.Index}");
      if (match.Groups.Count > 1) {
         GroupCollection groups = match.Groups;
         for (int grpCtr = 1; grpCtr <= groups.Count - 1; grpCtr++) {
            Console.WriteLine($"   Group {grpCtr}: '{groups[grpCtr].Value}' at index {groups[grpCtr].Index}");
            int captureCtr = 0;
            foreach (Capture capture in groups[grpCtr].Captures) {
               captureCtr++;
               Console.WriteLine($"      Capture {captureCtr}: '{capture.Value}' at index {capture.Index}");
            }
         }
      }
   }
}
// The example displays the following output:
//       Match: 'aaa' at index 0
//          Group 1: '' at index 3
//             Capture 1: 'a' at index 0
//             Capture 2: 'a' at index 1
//             Capture 3: 'a' at index 2
//             Capture 4: '' at index 3
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "(a?)*"
        Dim input As String = "aaabbb"
        Dim match As Match = Regex.Match(input, pattern)
        Console.WriteLine("Match: '{0}' at index {1}",
                          match.Value, match.Index)
        If match.Groups.Count > 1 Then
            Dim groups As GroupCollection = match.Groups
            For grpCtr As Integer = 1 To groups.Count - 1
                Console.WriteLine("   Group {0}: '{1}' at index {2}",
                                  grpCtr,
                                  groups(grpCtr).Value,
                                  groups(grpCtr).Index)
                Dim captureCtr As Integer = 0
                For Each capture As Capture In groups(grpCtr).Captures
                    captureCtr += 1
                    Console.WriteLine("      Capture {0}: '{1}' at index {2}",
                                      captureCtr, capture.Value, capture.Index)
                Next
            Next
        End If
    End Sub
End Module
' The example displays the following output:
'       Match: 'aaa' at index 0
'          Group 1: '' at index 3
'             Capture 1: 'a' at index 0
'             Capture 2: 'a' at index 1
'             Capture 3: 'a' at index 2
'             Capture 4: '' at index 3

若要查看定義擷取數目上下限的擷取群組和定義固定擷取數目的擷取群組之間的實際差異,請考慮規則運算式模式 (a\1|(?(1)\1)){0,2}(a\1|(?(1)\1)){2}。 這兩個規則運算式都是由單一擷取群組組成,在下表中定義:

模式 描述
(a\1 要麼比對 a,或者比對第一個擷取的群組值...
|(?(1) … 或測試第一個擷取的群組是否已定義。 (?(1) 建構不會定義擷取群組。
\1)) 如果第一個擷取的群組存在,即比對其值。 如果群組不存在,則會將群組比對到 String.Empty

第一個規則運算式嘗試比對這個模式零到兩次,第二個則比對剛好兩次。 因為第一個模式透過 String.Empty 的第一個擷取就能達到擷取數目下限,所以絕不會重複嘗試比對 a\1{0,2} 數量詞在最後一次迭代中只允許空比對。 相反地,第二個正則表達式會匹配 a ,因為它會重新評估 a\1。 最小反覆次數為 2,這會強制引擎在發生空比對後重複操作。

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern, input;

      pattern = @"(a\1|(?(1)\1)){0,2}";
      input = "aaabbb";

      Console.WriteLine($"Regex pattern: {pattern}");
      Match match = Regex.Match(input, pattern);
      Console.WriteLine($"Match: '{match.Value}' at position {match.Index}.");
      if (match.Groups.Count > 1) {
         for (int groupCtr = 1; groupCtr <= match.Groups.Count - 1; groupCtr++)
         {
            Group group = match.Groups[groupCtr];
            Console.WriteLine($"   Group: {groupCtr}: '{group.Value}' at position {group.Index}.");
            int captureCtr = 0;
            foreach (Capture capture in group.Captures) {
               captureCtr++;
               Console.WriteLine($"      Capture: {captureCtr}: '{capture.Value}' at position {capture.Index}.");
            }
         }
      }
      Console.WriteLine();

      pattern = @"(a\1|(?(1)\1)){2}";
      Console.WriteLine($"Regex pattern: {pattern}");
      match = Regex.Match(input, pattern);
         Console.WriteLine($"Matched '{match.Value}' at position {match.Index}.");
      if (match.Groups.Count > 1) {
         for (int groupCtr = 1; groupCtr <= match.Groups.Count - 1; groupCtr++)
         {
            Group group = match.Groups[groupCtr];
            Console.WriteLine($"   Group: {groupCtr}: '{group.Value}' at position {group.Index}.");
            int captureCtr = 0;
            foreach (Capture capture in group.Captures) {
               captureCtr++;
               Console.WriteLine($"      Capture: {captureCtr}: '{capture.Value}' at position {capture.Index}.");
            }
         }
      }
   }
}
// The example displays the following output:
//       Regex pattern: (a\1|(?(1)\1)){0,2}
//       Match: '' at position 0.
//          Group: 1: '' at position 0.
//             Capture: 1: '' at position 0.
//
//       Regex pattern: (a\1|(?(1)\1)){2}
//       Matched 'a' at position 0.
//          Group: 1: 'a' at position 0.
//             Capture: 1: '' at position 0.
//             Capture: 2: 'a' at position 0.
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern, input As String

        pattern = "(a\1|(?(1)\1)){0,2}"
        input = "aaabbb"

        Console.WriteLine("Regex pattern: {0}", pattern)
        Dim match As Match = Regex.Match(input, pattern)
        Console.WriteLine("Match: '{0}' at position {1}.",
                          match.Value, match.Index)
        If match.Groups.Count > 1 Then
            For groupCtr As Integer = 1 To match.Groups.Count - 1
                Dim group As Group = match.Groups(groupCtr)
                Console.WriteLine("   Group: {0}: '{1}' at position {2}.",
                                  groupCtr, group.Value, group.Index)
                Dim captureCtr As Integer = 0
                For Each capture As Capture In group.Captures
                    captureCtr += 1
                    Console.WriteLine("      Capture: {0}: '{1}' at position {2}.",
                                      captureCtr, capture.Value, capture.Index)
                Next
            Next
        End If
        Console.WriteLine()

        pattern = "(a\1|(?(1)\1)){2}"
        Console.WriteLine("Regex pattern: {0}", pattern)
        match = Regex.Match(input, pattern)
        Console.WriteLine("Matched '{0}' at position {1}.",
                          match.Value, match.Index)
        If match.Groups.Count > 1 Then
            For groupCtr As Integer = 1 To match.Groups.Count - 1
                Dim group As Group = match.Groups(groupCtr)
                Console.WriteLine("   Group: {0}: '{1}' at position {2}.",
                                  groupCtr, group.Value, group.Index)
                Dim captureCtr As Integer = 0
                For Each capture As Capture In group.Captures
                    captureCtr += 1
                    Console.WriteLine("      Capture: {0}: '{1}' at position {2}.",
                                      captureCtr, capture.Value, capture.Index)
                Next
            Next
        End If
    End Sub
End Module
' The example displays the following output:
'       Regex pattern: (a\1|(?(1)\1)){0,2}
'       Match: '' at position 0.
'          Group: 1: '' at position 0.
'             Capture: 1: '' at position 0.
'       
'       Regex pattern: (a\1|(?(1)\1)){2}
'       Matched 'a' at position 0.
'          Group: 1: 'a' at position 0.
'             Capture: 1: '' at position 0.
'             Capture: 2: 'a' at position 0.

另請參閱