群組建構
群組建構會描寫規則運算式的子運算式,而且會擷取輸入字串的子字串。 您可以使用群組建構來執行下列動作:
比對在輸入字串中重複的子運算式。
將數量詞套用至具有多個規則運算式語言項目的子運算式。 如需數量詞的詳細資訊,請參閱數量詞。
在由 Regex.Replace 和 Match.Result 方法傳回的字串中包含子運算式。
從 Match.Groups 屬性擷取個別的子運算式,並從整體相符文字分別處理它們。
.NET Framework 支援下列規則運算式群組建構:
符合的子運算式
已命名的符合子運算式
對稱群組定義
非擷取的群組
群組選項
零寬度右合樣 (Positive Lookahead) 判斷提示
零寬度右不合樣 (Negative Lookahead) 判斷提示
零寬度左合樣 (Positive Lookbehind) 判斷提示
零寬度左不合樣 (Negative Lookbehind) 判斷提示
非回溯子運算式
群組建構與規則運算式物件
相符的子運算式
下列群組建構會擷取相符的子運算式:
( subexpression )
其中,subexpression 是任何有效的規則運算式模式。 使用括號的擷取會根據規則運算式中右括號的順序,自動從左到右編號 (從一開始)。 編號為零的擷取是整個規則運算式模式比對的文字。
注意事項 |
---|
如果規則運算式模式比對方法的 RegexOptions 參數包含 RegexOptions.ExplicitCapture 旗標,或者 n 選項套用到這個子運算式 (請參閱選項本主題稍後的群組選項),則不會擷取相符的子運算式。 |
有四種方式可以存取擷取群組:
藉由使用規則運算式內的反向參考建構。 使用語法 \數字 即可在同一個規則運算式中參考相符的子運算式,其中 數字 是擷取子運算式的序數數目。
藉由使用規則運算式內的具名反向參考建構。 使用語法 \k<數字> 即可在同一個規則運算式中參考相符的子運算式,其中數字 是擷取子運算式的序數數目。 擷取子運算式的預設名稱與其序號完全相同。 如需詳細資訊,請參閱本主題稍後的具名比對子運算式。
透過使用 Regex.Replace 或 Match.Result 方法呼叫中的 $號碼r 取代序列,其中號碼是擷取子運算式的序號。
以程式設計的方式,藉由使用 Match.Groups 屬性所傳回的 GroupCollection 物件。 集合中位置零的成員代表整個規則運算式比對。 每個後續成員均代表一個相符的子運算式。 如需詳細資訊,請參閱群組建構和規則運算式物件章節。
下列範例說明可在文字中識別重複字組的規則運算式。 規則運算式模式的兩個擷取群組代表兩個重複字組的執行個體。 會擷取第二個執行個體以報告它在輸入字串中的起始位置。
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim pattern As String = "(\w+)\s(\1)\W"
Dim input As String = "He said that that was the the correct answer."
For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
Console.WriteLine("Duplicate '{0}' found at positions {1} and {2}.", _
match.Groups(1).Value, match.Groups(1).Index, match.Groups(2).Index)
Next
End Sub
End Module
' The example displays the following output:
' Duplicate 'that' found at positions 8 and 13.
' Duplicate 'the' found at positions 22 and 26.
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = @"(\w+)\s(\1)";
string input = "He said that that was the the correct answer.";
foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
Console.WriteLine("Duplicate '{0}' found at positions {1} and {2}.",
match.Groups[1].Value, match.Groups[1].Index, match.Groups[2].Index);
}
}
// The example displays the following output:
// Duplicate 'that' found at positions 8 and 13.
// Duplicate 'the' found at positions 22 and 26.
規則運算式模式如下所示:
(\w+)\s(\1)\W
下表顯示規則運算式模式的解譯方式。
模式 |
描述 |
---|---|
(\w+) |
比對一個或多個文字字元。 這是第一個擷取群組。 |
\s |
比對空白字元。 |
(\1) |
比對第一個擷取群組中的字串。 這是第二個擷取群組。 範例會將它指派給擷取的群組,以便從 Match.Index 屬性擷取重複字組的起始位置。 |
\W |
比對非字組字元,包括空格和標點符號。 如此可避免規則運算式模式比對以第一個擷取群組中的字組開頭的字組。 |
具名的相符子運算式
下列群組建構會擷取相符的子運算式,並可讓您依名稱或編號存取它:
(?<name>subexpression)
或:
(?'name' subexpression)
其中名稱 是有效的群組名稱,而子運算式 是任何有效的規則運算式模式。 name 不可包含任何標點符號字元,而且不能以數字當做開頭。
注意事項 |
---|
如果規則運算式模式比對方法的 RegexOptions 參數包含 RegexOptions.ExplicitCapture 旗標,或者 n 選項套用到這個子運算式 (請參閱本主題稍後的 群組選項),擷取子運算式的唯一方式是明確地命名擷取群組。 |
您可以透過下列方式存取具名的擷取群組:
藉由使用規則運算式內的具名反向參考建構。 相同的規則運算式會利用 \k<名稱> 語法參考相符的子運算式,其中名稱 是擷取子運算式的名稱。
藉由使用規則運算式內的反向參考建構。 使用語法 \數字 即可在同一個規則運算式中參考相符的子運算式,其中 數字 是擷取子運算式的序數數目。 具名的相符子運算式會在相符的子運算式之後,從左到右連續編號。
透過使用 Regex.Replace 或 Match.Result 方法呼叫中的 ${名稱} 取代序列,其中名稱是擷取子運算式的名稱。
透過使用 Regex.Replace 或 Match.Result 方法呼叫中的 $號碼> 取代序列,其中號碼是擷取子運算式的序號。
以程式設計的方式,藉由使用 Match.Groups 屬性所傳回的 GroupCollection 物件。 集合中位置零的成員代表整個規則運算式比對。 每個後續成員均代表一個相符的子運算式。 具名的擷取群組會儲存在集合中的編號擷取群組之後。
以程式設計的方式,藉由提供子運算式名稱給 GroupCollection 物件索引子 (在 C# 中) 中或其 Item 屬性 (在 Visual Basic 中)。
簡單規則運算式模式說明,如何以程式設計方式或使用規則運算式語言語法來參考編號 (未命名) 群組和具名群組 規則運算式 ((?<One>abc)\d+)?(?<Two>xyz)(.*) 會依編號和名稱產生下列擷取群組。 第一個擷取群組 (編號 0) 永遠參考整個模式。
數字 |
名稱 |
模式 |
---|---|---|
0 |
0 (預設名稱) |
((?<One>abc)\d+)?(?<Two>xyz)(.*) |
1 |
1 (預設名稱) |
((?<One>abc)\d+) |
2 |
2 (預設名稱) |
(.*) |
3 |
One |
(?<One>abc) |
4 |
Two |
(?<Two>xyz) |
下列範例說明規則運算式,該規則運算式會識別重複的字組,以及在每個重複字組之後的字組。 規則運算式模式會定義兩個具名的子運算式:duplicateWord (用來代表重複的字組) 和 nextWord (用來重複字組之後的字組)。
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim pattern As String = "(?<duplicateWord>\w+)\s\k<duplicateWord>\W(?<nextWord>\w+)"
Dim input As String = "He said that that was the the correct answer."
Console.WriteLine(Regex.Matches(input, pattern, RegexOptions.IgnoreCase).Count)
For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
Console.WriteLine("A duplicate '{0}' at position {1} is followed by '{2}'.", _
match.Groups("duplicateWord").Value, match.Groups("duplicateWord").Index, _
match.Groups("nextWord").Value)
Next
End Sub
End Module
' The example displays the following output:
' A duplicate 'that' at position 8 is followed by 'was'.
' A duplicate 'the' at position 22 is followed by 'correct'.
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = @"(?<duplicateWord>\w+)\s\k<duplicateWord>\W(?<nextWord>\w+)";
string input = "He said that that was the the correct answer.";
foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
Console.WriteLine("A duplicate '{0}' at position {1} is followed by '{2}'.",
match.Groups["duplicateWord"].Value, match.Groups["duplicateWord"].Index,
match.Groups["nextWord"].Value);
}
}
// The example displays the following output:
// A duplicate 'that' at position 8 is followed by 'was'.
// A duplicate 'the' at position 22 is followed by 'correct'.
規則運算式模式如下所示:
(?<duplicateWord>\w+)\s\k<duplicateWord>\W(?<nextWord>\w+)
下表顯示規則運算式的解譯方式。
模式 |
描述 |
---|---|
(?<duplicateWord>\w+) |
比對一個或多個文字字元。 將此擷取群組命名為 duplicateWord。 |
\s |
比對空白字元。 |
\k<duplicateWord> |
比對名為 duplicateWord 之擷取群組中的字串。 |
\W |
比對非字組字元,包括空格和標點符號。 如此可避免規則運算式模式比對以第一個擷取群組中的字組開頭的字組。 |
(?<nextWord>\w+) |
比對一個或多個文字字元。 將此擷取群組命名為 nextWord。 |
平衡群組定義
平衡群組定義會刪除先前定義的群組,並在目前的群組中儲存先前定義的群組和目前群組之間的間隔。 這個群組建構具有下列格式:
(?<name1-name2>subexpression)
或:
(?'name1-name2' subexpression)
其中 name1 是目前的群組 (選擇性), name2 為先前定義的群組,而 subexpression 則是任何有效的規則運算式模式。 平衡群組定義會刪除 name2 的定義,並將 name2 和 name1 之間的間隔儲存在 name1。 如果沒有定義 name2 群組,比對會回溯。 因為刪除 name2 的最後一個定義會顯露 name2 先前的定義,所以這個建構可讓您使用 name2 群組的擷取堆疊做為計數器,以追蹤巢狀建構 (例如括號) 或開放及封閉括號。
平衡群組定義使用 name2 做為堆疊。 每個巢狀建構的起始字元均在群組及 Group.Captures 集合中。 結尾字元相符時,會從群組中移除其相對應的開頭字元,並將 Captures 集合減一。 比對過所有巢狀建構的開頭和結尾字元後,name1 會是空的。
注意事項 |
---|
將下列範例中的規則運算式修改為使用適當的巢狀建構開始和結尾字元之後,您可以使用該規則運算式來處理大多數的巢狀建構,例如數學運算式或包含多個巢狀方法呼叫的程式碼行。 |
下列程式碼範例使用對稱群組定義來比對輸入字串內的左右角括號 (<>)。 範例會定義兩個具名群組 (Open 與 Close),其用法類似追蹤角括號相符配對的堆疊。 會將每個擷取到的左角括號推入至 Open 群組的擷取集合,並將每個擷取到的右角括號推入至 Close 群組的擷取集合。 平衡群組定義可確保每個左角括號都有一個相符的右角括號。 如果沒有,唯有當 Open 群組不是空的 (也因此尚未關閉所有巢狀建構) 時,才會評估最終的子模式 ((?(Open)(?!)))。 如果評估最終子模式,比對會失敗,因為輸入的字串不應包含子字串 ?! 的任何項目。
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim pattern As String = "^[^<>]*" & _
"(" + "((?'Open'<)[^<>]*)+" & _
"((?'Close-Open'>)[^<>]*)+" + ")*" & _
"(?(Open)(?!))$"
Dim input As String = "<abc><mno<xyz>>"
Dim rgx AS New Regex(pattern)'
Dim m As Match = Regex.Match(input, pattern)
If m.Success Then
Console.WriteLine("Input: ""{0}"" " & vbCrLf & "Match: ""{1}""", _
input, m)
Dim grpCtr As Integer = 0
For Each grp As Group In m.Groups
Console.WriteLine(" Group {0}: {1}", grpCtr, grp.Value)
grpCtr += 1
Dim capCtr As Integer = 0
For Each cap As Capture In grp.Captures
Console.WriteLine(" Capture {0}: {1}", capCtr, cap.Value)
capCtr += 1
Next
Next
Else
Console.WriteLine("Match failed.")
End If
End Sub
End Module
' The example displays the following output:
' Input: "<abc><mno<xyz>>"
' Match: "<abc><mno<xyz>>"
' Group 0: <abc><mno<xyz>>
' Capture 0: <abc><mno<xyz>>
' Group 1: <mno<xyz>>
' Capture 0: <abc>
' Capture 1: <mno<xyz>>
' Group 2: <xyz
' Capture 0: <abc
' Capture 1: <mno
' Capture 2: <xyz
' Group 3: >
' Capture 0: >
' Capture 1: >
' Capture 2: >
' Group 4:
' Group 5: mno<xyz>
' Capture 0: abc
' Capture 1: xyz
' Capture 2: mno<xyz>
using System;
using System.Text.RegularExpressions;
class Example
{
public static void Main()
{
string pattern = "^[^<>]*" +
"(" +
"((?'Open'<)[^<>]*)+" +
"((?'Close-Open'>)[^<>]*)+" +
")*" +
"(?(Open)(?!))$";
string input = "<abc><mno<xyz>>";
Match m = Regex.Match(input, pattern);
if (m.Success == true)
{
Console.WriteLine("Input: \"{0}\" \nMatch: \"{1}\"", input, m);
int grpCtr = 0;
foreach (Group grp in m.Groups)
{
Console.WriteLine(" Group {0}: {1}", grpCtr, grp.Value);
grpCtr++;
int capCtr = 0;
foreach (Capture cap in grp.Captures)
{
Console.WriteLine(" Capture {0}: {1}", capCtr, cap.Value);
capCtr++;
}
}
}
else
{
Console.WriteLine("Match failed.");
}
}
}
// The example displays the following output:
// Input: "<abc><mno<xyz>>"
// Match: "<abc><mno<xyz>>"
// Group 0: <abc><mno<xyz>>
// Capture 0: <abc><mno<xyz>>
// Group 1: <mno<xyz>>
// Capture 0: <abc>
// Capture 1: <mno<xyz>>
// Group 2: <xyz
// Capture 0: <abc
// Capture 1: <mno
// Capture 2: <xyz
// Group 3: >
// Capture 0: >
// Capture 1: >
// Capture 2: >
// Group 4:
// Group 5: mno<xyz>
// Capture 0: abc
// Capture 1: xyz
// Capture 2: mno<xyz>
規則運算式模式是:
^[^<>]*(((?'Open'<)[^<>]*)+((?'Close-Open'>)[^<>]*)+)*(?(Open)(?!))$
規則運算式解譯如下:
模式 |
描述 |
---|---|
^ |
在字串開頭開始。 |
[^<>]* |
比對零或多個不是左或右角括號的字元。 |
(?'Open'<) |
比對左角括號,並將它指派給名為 Open 的群組。 |
[^<>]* |
比對零或多個不是左或右角括號的字元。 |
((?'Open'<)[^<>]*) + |
比對出現一或多次的左角括號 (後面接零或多個非左或右角括號的字元)。 這是第二個擷取群組。 |
(?'Close-Open'>) |
比對右角括弧、將 Open 群組和目前群組之間的子字串指派給 Close 群組,並且刪除 Open 群組的定義。 |
[^<>]* |
比對不是左或右括號且出現零或多次的任何字元。 |
((?'Close-Open'>)[^<>]*)+ |
比對出現一或多次的右角括號 (後面接出現零或多次的任何字元,且此字元不是左或右角括號)。 比對右角括弧時,會將 Open 群組和目前群組之間的子字串指派給 Close 群組,並且刪除 Open 群組的定義。 這是第三個擷取群組。 |
(((?'Open'<)[^<>]*)+((?'Close-Open'>)[^<>]*)+)* |
比對出現零或多次的下列模式:出現一或多次左角括號,後面接零或多個非角括號字元、出現多次的右角括號、出現零或多次的非角括號。 比對右角括弧時,會刪除 Open 群組的定義,並將 Open 群組和目前的群組之間的子字串指派給 Close 群組。 這是第一個擷取群組。 |
(?(Open)(?!)) |
如果 Open 群組存在,請比對問號和驚嘆號。 如果 Open 群組已定義,比對會失敗,表示角括弧不對稱。 |
$ |
比對輸入字串的結尾。 |
最終的子運算式 ((?(Open)(?!))) 表示輸入字串中的巢狀建構是否平衡 (例如每個左角括號是否均有成對的右角括號)。 它會使用以有效擷取群組為基礎的條件式比對,如需詳細資訊,請參閱替代建構。 如果已定義 Open 群組,規則運算式引擎會嘗試比對輸入字串中的子運算式 (?!)。 只有當巢狀建構不對稱時,才應定義 Open 群組。 因此,要在輸入字串中比對的模式應是不能發生在輸入字串中的模式,否則會使比對失敗。
在範例中,規則運算式引擎會計算輸入字串 ("<abc><mno<xyz>>") 時,如下表所示。
步驟 |
模式 |
結果 |
---|---|---|
1 |
^ |
在輸入字串的開頭開始比對 |
2 |
[^<>]* |
尋找左角括號之前的非角括號字元,找不到相符結果。 |
3 |
(((?'Open'<) |
比對 "<abc>" 中的左角括號,然後將它指派給 Open 群組。 |
4 |
[^<>]* |
比對 「abc」。 |
5 |
)+ |
"<abc>" 是第二個擷取群組的値。 輸入字串中的下一個字元不是左角括號,所以規則運算式引擎不會迴圈到 (?'Open'<)[^<>]*) 子模式。 |
6 |
((?'Close-Open'>) |
比對 "<abc>" 中的最終右角括號、指派 "abc" (Open 群組和右角括號之間的子字串) 給 Close 群組,並刪除 Open 群組目前的值 ("<"),使其保留空白。 |
7 |
[^<>]* |
尋找右角括號之後的非角括號字元,找不到相符結果。 |
8 |
)+ |
第三個擷取群組的値是 ">"。 輸入字串中的下一個字元不是右角括號,所以規則運算式引擎不會迴圈到 ((?'Close-Open'>)[^<>]*) 子模式。 |
9 |
)* |
第一個擷取群組的値是 "<abc>"。 輸入字串中的下一個字元是左角括號,所以規則運算式引擎會循環回到 (((?'Open'<) 子模式。 |
10 |
(((?'Open'<) |
比對 "<mno>" 中的左角括號,然後將它指派給 Open 群組。 現在其 Group.Captures 集合有單一的值 ("<")。 |
11 |
[^<>]* |
比對 "mno"。 |
12 |
)+ |
"<mno>" 是第二個擷取群組的値。 輸入字串中的下一個字元是左角括號,所以規則運算式引擎會循環回到 (?'Open'<)[^<>]*) 子模式。 |
13 |
(((?'Open'<) |
比對 "<xyz>" 中的左角括號,然後將它指派給 Open 群組。 Open 群組的 Group.Captures 集合現在包含兩個擷取:"<mno>" 的左角括號及 "<xyz>" 的左角括號。 |
14 |
[^<>]* |
比對 "xyz"。 |
15 |
)+ |
"<xyz>" 是第二個擷取群組的値。 輸入字串中的下一個字元不是左角括號,所以規則運算式引擎不會迴圈到 (?'Open'<)[^<>]*) 子模式。 |
16 |
((?'Close-Open'>) |
比對 "<xyz>" 中的右角括號。" xyz",指派 Open 群組和右角括號之間的子字串給 Close 群組,並刪除 Open 群組目前的值。 前一個擷取 ("<mno>" 中的左角括號) 的值會成為 Open 群組目前的值。 Open 群組的 Captures 集合現在包含單一擷取 ("< xyz >" 的左角括號)。 |
17 |
[^<>]* |
尋找非角括號字元,找不到相符結果。 |
18 |
)+ |
第三個擷取群組的値是 ">"。 輸入字串中的下一個字元是右角括號,所以規則運算式引擎會循環回到 ((?'Close-Open'>)[^<>]*) 子模式。 |
19 |
((?'Close-Open'>) |
比對 "xyz>>"中的最終右角括號、指派 "mno<xyz>" (Open 群組和右角括號之間的子字串) 給 Close 群組,並刪除 Open 群組目前的值。 Open 群組現在是空的。 |
20 |
[^<>]* |
尋找非角括號字元,找不到相符結果。 |
21 |
)+ |
第三個擷取群組的値是 ">"。 輸入字串中的下一個字元不是右角括號,所以規則運算式引擎不會迴圈到 ((?'Close-Open'>)[^<>]*) 子模式。 |
22 |
)* |
第一個擷取群組的値是 "<mno<xyz>>"。 輸入字串中的下一個字元不是左角括號,所以規則運算式引擎不會迴圈到 (((?'Open'<) 子模式。 |
23 |
(?(Open)(?!)) |
Open 群組未定義,所以不會嘗試比對。 |
24 |
$ |
比對輸入字串的結尾。 |
非擷取的群組
下列群組建構不會擷取子運算式比對的子字串:
(?:subexpression)
其中,subexpression 是任何有效的規則運算式模式。 非擷取群組建構通常用於將數量詞套用於群組,但該群組所擷取的子字串當一個數量詞會套用到一個群組,但該群組所擷取的子字串並不需要時。
注意事項 |
---|
如果規則運算式包含巢狀的群組建構,外部的非擷取群組建構並不會套用到內部的巢狀的群組建構。 |
下列範例說明包含非擷取群組的規則運算式。 請注意,輸出不包含任何擷取群組。
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim pattern As String = "(?:\b(?:\w+)\W*)+\."
Dim input As String = "This is a short sentence."
Dim match As Match = Regex.Match(input, pattern)
Console.WriteLine("Match: {0}", match.Value)
For ctr As Integer = 1 To match.Groups.Count - 1
Console.WriteLine(" Group {0}: {1}", ctr, match.Groups(ctr).Value)
Next
End Sub
End Module
' The example displays the following output:
' Match: This is a short sentence.
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = @"(?:\b(?:\w+)\W*)+\.";
string input = "This is a short sentence.";
Match match = Regex.Match(input, pattern);
Console.WriteLine("Match: {0}", match.Value);
for (int ctr = 1; ctr < match.Groups.Count; ctr++)
Console.WriteLine(" Group {0}: {1}", ctr, match.Groups[ctr].Value);
}
}
// The example displays the following output:
// Match: This is a short sentence.
規則運算式 (?:\b(?:\w+)\W*)+\. 會比對以句號結束的句子。 因為規則運算式著重在句子而不是個別的字組,因此會以獨佔方式使用群組建構做為數量詞。 規則運算式模式的解譯方式如下表所示。
模式 |
描述 |
---|---|
\b |
開始字緣比對。 |
(?:\w+) |
比對一個或多個文字字元。 請勿將相符的文字指派給所擷取的群組。 |
\W* |
比對零個或多個非文字字元。 |
(?:\b(?:\w+)\W*)+ |
比對一或多個於字元界線開始、後面接零或多個非字組字元一或多次的字組字元模式。 請勿將相符的文字指派給所擷取的群組。 |
\. |
比對句點。 |
群組選項
下列群組建構會套用或停用子運算式內指定的選項:
(?imnsx-imnsx: subexpression )
其中,subexpression 是任何有效的規則運算式模式。 例如,(?i-s:) 開啟不區分大小寫功能以及停用單行模式。 如需可指定之內嵌選項的詳細資訊,請參閱規則運算式選項。
注意事項 |
---|
您可以使用 System.Text.RegularExpressions.Regex 類別建構函式或靜態方法,指定套用至整個規則運算式而不只是子運算式的選項。您也可以指定使用 (?imnsx-imnsx) 語言建構,指定在規則運算式中特定點之後套用的內嵌選項。 |
群組選項建構不是擷取群組。 也就是說,雖然 子運算式 所擷取之字串中的任何部分均包含在符合項目中,但不包含在擷取的群組中,也不用於填入 GroupCollection 物件。
例如,下列範例中的規則運算式 \b(?ix: d \w+)\s 在群組建構中使用內嵌選項進行不區分大小寫的比對,並在識別以字母 "d" 開頭的所有文字時忽略圖樣空格。 此規則運算式的定義方式如下表所示。
模式 |
描述 |
---|---|
\b |
開始字緣比對。 |
(?ix: d \w+) |
使用不區分大小寫的比對並忽略這種模式中的空白字元,比對後面接一個或多個字組字元的 "d"。 |
\s |
比對空白字元。 |
Dim pattern As String = "\b(?ix: d \w+)\s"
Dim input As String = "Dogs are decidedly good pets."
For Each match As Match In Regex.Matches(input, pattern)
Console.WriteLine("'{0}' found at index {1}.", match.Value, match.Index)
Next
' The example displays the following output:
' 'Dogs ' found at index 0.
' 'decidedly ' found at index 9.
string pattern = @"\b(?ix: d \w+)\s";
string input = "Dogs are decidedly good pets.";
foreach (Match match in Regex.Matches(input, pattern))
Console.WriteLine("'{0}// found at index {1}.", match.Value, match.Index);
// The example displays the following output:
// 'Dogs // found at index 0.
// 'decidedly // found at index 9.
零寬度右合樣 (Positive Lookahead) 判斷提示
下列群組建構會定義零寬度右合樣判斷提示:
(?= subexpression )
其中,subexpression 是任何規則運算式模式。 雖然比對子字串不會包含在比對結果中,但輸入字串必須符合子運算式中的規則運算式模式,才能順利比對。 零寬度右合樣判斷提示不會回溯。
通常會在規則運算式模式的結尾處找到零寬度右合樣判斷提示。 它會定義子字串,這個子字串必須位於字串的結尾處,才會發生比對,但不可包含在比對中。 它也有助於防止過度回溯。 您可以使用零寬度右合樣判斷提示,確保特定的擷取群組是以符合針對該擷取群組所定義之模式子集的文字開頭。 例如,如果擷取群組符合連續的字組字元,您可以使用零寬度右合樣判斷提示要求第一個字元必須是大寫英數字元。
下列範例使用以零寬度右合樣判斷提示,比對輸入字串中在動詞 "是" 之前的字組。
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim pattern As String = "\b\w+(?=\sis\b)"
Dim inputs() As String = { "The dog is a Malamute.", _
"The island has beautiful birds.", _
"The pitch missed home plate.", _
"Sunday is a weekend day." }
For Each input As String In inputs
Dim match As Match = Regex.Match(input, pattern)
If match.Success Then
Console.WriteLine("'{0}' precedes 'is'.", match.Value)
Else
Console.WriteLine("'{0}' does not match the pattern.", input)
End If
Next
End Sub
End Module
' The example displays the following output:
' 'dog' precedes 'is'.
' 'The island has beautiful birds.' does not match the pattern.
' 'The pitch missed home plate.' does not match the pattern.
' 'Sunday' precedes 'is'.
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = @"\b\w+(?=\sis\b)";
string[] inputs = { "The dog is a Malamute.",
"The island has beautiful birds.",
"The pitch missed home plate.",
"Sunday is a weekend day." };
foreach (string input in inputs)
{
Match match = Regex.Match(input, pattern);
if (match.Success)
Console.WriteLine("'{0}' precedes 'is'.", match.Value);
else
Console.WriteLine("'{0}' does not match the pattern.", input);
}
}
}
// The example displays the following output:
// 'dog' precedes 'is'.
// 'The island has beautiful birds.' does not match the pattern.
// 'The pitch missed home plate.' does not match the pattern.
// 'Sunday' precedes 'is'.
規則運算式 \b\w+(?=\sis\b) 的解譯方式如下表所示。
模式 |
描述 |
---|---|
\b |
開始字緣比對。 |
\w+ |
比對一個或多個文字字元。 |
(?=\sis\b) |
決定字組字元後面是否跟著空白字元和字串「is」,並在單字界線上結束。 如果是這樣,比對就是成功的。 |
零寬度右不合樣 (Negative Lookahead) 判斷提示
下列群組建構會定義零寬度右不合樣判斷提示:
(?! subexpression )
其中,subexpression 是任何規則運算式模式。 雖然比對字串不會包含在比對結果中,但輸入字串不能符合子運算式中的規則運算式模式,才能順利比對。
零寬度右不合樣判斷提示通常用於規則運算式的開頭或結尾。 在規則運算式開頭,它可以定義不應比對的特定模式,而規則運算式的開頭會定義類似但更一般的模式供比對。 在這種情況下,它通常用於限制回溯。 在規則運算式結尾,它可以定義不能發生在比對結尾處的子運算式。
下列範例會定義規則運算式,此規則運算式會在運算式開頭使用零寬度左合樣判斷提示,比對不是以 "un" 開頭的字組。
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim pattern As String = "\b(?!un)\w+\b"
Dim input As String = "unite one unethical ethics use untie ultimate"
For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
Console.WriteLine(match.Value)
Next
End Sub
End Module
' The example displays the following output:
' one
' ethics
' use
' ultimate
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = @"\b(?!un)\w+\b";
string input = "unite one unethical ethics use untie ultimate";
foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
Console.WriteLine(match.Value);
}
}
// The example displays the following output:
// one
// ethics
// use
// ultimate
規則運算式 \b(?!un)\w+\b 的解譯方式如下表所示。
模式 |
描述 |
---|---|
\b |
開始字緣比對。 |
(?!un) |
決定接下來的兩個字元是否為 「un」。 如果不是,可能會有符合項目。 |
\w+ |
比對一個或多個文字字元。 |
\b |
結束字緣比對。 |
下列範例會定義規則運算式,該規則運算式會在規則運算式的結尾使用零寬度左合樣判斷提示,比對結尾不是標點符號字元的字組。
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim pattern As String = "\b\w+\b(?!\p{P})"
Dim input As String = "Disconnected, disjointed thoughts in a sentence fragment."
For Each match As Match In Regex.Matches(input, pattern)
Console.WriteLine(match.Value)
Next
End Sub
End Module
' The example displays the following output:
' disjointed
' thoughts
' in
' a
' sentence
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = @"\b\w+\b(?!\p{P})";
string input = "Disconnected, disjointed thoughts in a sentence fragment.";
foreach (Match match in Regex.Matches(input, pattern))
Console.WriteLine(match.Value);
}
}
// The example displays the following output:
// disjointed
// thoughts
// in
// a
// sentence
規則運算式 \b\w+\b(?!\p{P}) 的解譯方式如下表所示。
模式 |
描述 |
---|---|
\b |
開始字緣比對。 |
\w+ |
比對一個或多個文字字元。 |
\b |
結束字緣比對。 |
\p{P}) |
如果下一個字元不是標點符號 (如句號或逗號),比對會成功。 |
零寬度左合樣 (Positive Lookbehind) 判斷提示
下列群組建構會定義零寬度左合樣判斷提示:
(?<= subexpression )
其中,subexpression 是任何規則運算式模式。 雖然 subexpression 不會包含在比對結果中,但目前位置左邊的輸入字串中必須有子運算式,才能順利比對。 零寬度左合樣判斷提示不會回溯。
零寬度合樣判斷提示通常用於規則運算式的開頭。 它們定義的模式是比對的前置條件,雖然它不是比對結果的一部分。
例如,下列範例會比對二十一世紀年份的最後兩位數 (也就是說,「20」這個數字的優先順序高於所比對的字串)。
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim input As String = "2010 1999 1861 2140 2009"
Dim pattern As String = "(?<=\b20)\d{2}\b"
For Each match As Match In Regex.Matches(input, pattern)
Console.WriteLine(match.Value)
Next
End Sub
End Module
' The example displays the following output:
' 10
' 09
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string input = "2010 1999 1861 2140 2009";
string pattern = @"(?<=\b20)\d{2}\b";
foreach (Match match in Regex.Matches(input, pattern))
Console.WriteLine(match.Value);
}
}
// The example displays the following output:
// 10
// 09
規則運算式模式 (?<=\b20)\d{2}\b 的解譯方式如下表所示。
模式 |
描述 |
---|---|
\d{2} |
比對兩個十進位數字。 |
{?<=\b20) |
繼續比對 (如果字組界限中兩個十進位數字的前面是十進位數字 "20") |
\b |
結束字緣比對。 |
當擷取群組中的最後幾個字元必須是符合該群組規則運算式模式的字元子集時,還會使用零寬度左合樣 (Positive Lookbehind) 判斷提示來限制回溯。 例如,如果群組擷取所有連續的字組字元,您可以使用零寬度左合樣判斷提示要求最後一個字元必須是英數字元。
零寬度左不合樣 (Negative Lookbehind) 判斷提示
下列群組建構會定義零寬度左不合樣判斷提示:
(?<! subexpression )
其中,subexpression 是任何規則運算式模式。 目前位置左邊的輸入字串中不能有子運算式,才能順利比對。 不過,比對結果中不包含任何不符合 subexpression 的子字串。
零寬度不合樣判斷提示通常用於規則運算式的開頭。 它們所定義的模式會預先排除後續字串中的符合結果。 當擷取群組中的最後幾個字元不可以是符合該群組規則運算式模式的其中一個或多個字元時,還會使用這些判斷提示來限制回溯。 例如,如果群組擷取所有連續的字組字元,您可以使用零寬度左合樣判斷提示要求最後一個字元不可以是底線 (_)。
下列範例會比對一週當中任何一天 (非週末,也就是非星期六或星期日) 的日期。
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim dates() As String = { "Monday February 1, 2010", _
"Wednesday February 3, 2010", _
"Saturday February 6, 2010", _
"Sunday February 7, 2010", _
"Monday, February 8, 2010" }
Dim pattern As String = "(?<!(Saturday|Sunday) )\b\w+ \d{1,2}, \d{4}\b"
For Each dateValue As String In dates
Dim match As Match = Regex.Match(dateValue, pattern)
If match.Success Then
Console.WriteLine(match.Value)
End If
Next
End Sub
End Module
' The example displays the following output:
' February 1, 2010
' February 3, 2010
' February 8, 2010
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string[] dates = { "Monday February 1, 2010",
"Wednesday February 3, 2010",
"Saturday February 6, 2010",
"Sunday February 7, 2010",
"Monday, February 8, 2010" };
string pattern = @"(?<!(Saturday|Sunday) )\b\w+ \d{1,2}, \d{4}\b";
foreach (string dateValue in dates)
{
Match match = Regex.Match(dateValue, pattern);
if (match.Success)
Console.WriteLine(match.Value);
}
}
}
// The example displays the following output:
// February 1, 2010
// February 3, 2010
// February 8, 2010
規則運算式模式 (?<!(Saturday|Sunday) )\b\w+ \d{1,2}, \d{4}\b 的解譯方式如下表所示。
模式 |
描述 |
---|---|
\b |
開始字緣比對。 |
\w+ |
比對零或多個後面接空白字元的文字字元。 |
\d{1,2}, |
比對一或兩個後面接著空白字元和逗號的十進位數字。 |
\d{4}\b |
比對四個小數位數,並在字元界線結束比對。 |
(?<!(Saturday|Sunday) ) |
如果比對前面是「星期六」或「星期日」字串以外的內容,後面接著一個空格,表示比對成功。 |
非回溯子運算式
下列群組建構代表非回溯子運算式 (也稱為"窮盡"子運算式):
(?> subexpression )
其中,subexpression 是任何規則運算式模式。
正常情況下,如果規則運算式包含一個選擇性或替代的比對模式,而比對不成功,規則運算式引擎可以分支成多個方向,以比對模式中的輸入字串。 比對採用第一個分支時若找不到相符的項目,規則運算式引擎可以備份或回溯追蹤取得第一個分支的點,並且嘗試使用第二個分支進行比對。 這個處理序可以繼續執行,直到試過所有分支為止。
(?> 子運算式 ) 語言建構會停用回溯追蹤。 規則運算式引擎會盡可能比對輸入字串中的所有字元。 若不可能有其他相符項目,則會回溯嘗試其他模式比對。 (也就是子運算式只會比對會由子運算式單獨比對的字串,不會嘗試根據子運算是和之後的任何子運算式比對字串。)
如果您知道回溯不會成功,建議您使用這個選項。 防止規則運算式執行不必要的搜尋,以改善效能。
下列範例說明非回溯子運算式如何修改模式比對結果。 回溯的規則運算式會順利比對一系列重複的字元後面接在字元界線內再次出現同樣的字元,但非回溯規則運算式則不會。
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim inputs() As String = { "cccd.", "aaad", "aaaa" }
Dim back As String = "(\w)\1+.\b"
Dim noback As String = "(?>(\w)\1+).\b"
For Each input As String In inputs
Dim match1 As Match = Regex.Match(input, back)
Dim match2 As Match = Regex.Match(input, noback)
Console.WriteLine("{0}: ", input)
Console.Write(" Backtracking : ")
If match1.Success Then
Console.WriteLine(match1.Value)
Else
Console.WriteLine("No match")
End If
Console.Write(" Nonbacktracking: ")
If match2.Success Then
Console.WriteLine(match2.Value)
Else
Console.WriteLine("No match")
End If
Next
End Sub
End Module
' The example displays the following output:
' cccd.:
' Backtracking : cccd
' Nonbacktracking: cccd
' aaad:
' Backtracking : aaad
' Nonbacktracking: aaad
' aaaa:
' Backtracking : aaaa
' Nonbacktracking: No match
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string[] inputs = { "cccd.", "aaad", "aaaa" };
string back = @"(\w)\1+.\b";
string noback = @"(?>(\w)\1+).\b";
foreach (string input in inputs)
{
Match match1 = Regex.Match(input, back);
Match match2 = Regex.Match(input, noback);
Console.WriteLine("{0}: ", input);
Console.Write(" Backtracking : ");
if (match1.Success)
Console.WriteLine(match1.Value);
else
Console.WriteLine("No match");
Console.Write(" Nonbacktracking: ");
if (match2.Success)
Console.WriteLine(match2.Value);
else
Console.WriteLine("No match");
}
}
}
// The example displays the following output:
// cccd.:
// Backtracking : cccd
// Nonbacktracking: cccd
// aaad:
// Backtracking : aaad
// Nonbacktracking: aaad
// aaaa:
// Backtracking : aaaa
// Nonbacktracking: No match
非回溯規則運算式 (?>(\w)\1+).\b 的定義方式如下表所示。
模式 |
描述 |
---|---|
(\w) |
比對單一字組字元,並將其指派給第一個擷取群組。 |
\1+ |
比對第一個擷取子字串的值一次或多次。 |
. |
比對任何字元。 |
\b |
結束字緣比對。 |
(?>(\w)\1+) |
符合重複發生一或多次的字組字元,但不回溯比對字元界線的最後一個字元。 |
群組建構和規則運算式物件
規則運算式擷取群組比對的子字串以 System.Text.RegularExpressions.Group 物件代表,可從 Match.Groups 屬性傳回的System.Text.RegularExpressions.GroupCollection 物件擷取。 會填入 GroupCollection 物件,如下所示:
集合中的第一個 Group 物件 (索引為零的物件) 代表整個相符項目。
下一組 Group 物件代表未命名 (編號) 的擷取群組。 它們會依在規則運算式中定義的順序出現,從左到右。 這些群組的索引值範圍從 1 到集合中未命名擷取群組的數目。 (特定群組的索引就等於其編號的反向參考。 如需反向參考的詳細資訊,請參閱反向參考建構)。
最後一組 Group 物件代表具名擷取群組。 它們會依在規則運算式中定義的順序出現,從左到右。 第一個具名擷取群組的索引值大於最後一個未命名擷取群組的索引値。 如果規則運算式中沒有未命名的擷取群組,第一個具名擷取群組的索引值會是零。
如果您將數量詞套用至擷取群組,對應之 Group 物件的 Capture.Value、 Capture.Index和 Capture.Length 屬性會反映岀擷取群組最近擷取到的子字串。 您可以擷取一組完整的子字串,該子字串是由具有識別項的群組從 Group.Captures 屬性傳回之 CaptureCollection 物件擷取的。
下列範例說明 Group 和 Capture 物件之間的關聯性。
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim pattern As String = "(\b(\w+)\W+)+"
Dim input As String = "This is a short sentence."
Dim match As Match = Regex.Match(input, pattern)
Console.WriteLine("Match: {0}", match.Value)
For ctr As Integer = 1 To match.Groups.Count - 1
Console.WriteLine(" Group {0}: {1}", ctr, match.Groups(ctr).Value)
Dim capCtr As Integer = 0
For Each capture As Capture In match.Groups(ctr).Captures
Console.WriteLine(" Capture {0}: {1}", capCtr, capture.Value)
capCtr += 1
Next
Next
End Sub
End Module
' The example displays the following output:
' Match: This is a short sentence.
' Group 1: sentence.
' Capture 0: This
' Capture 1: is
' Capture 2: a
' Capture 3: short
' Capture 4: sentence.
' Group 2: sentence
' Capture 0: This
' Capture 1: is
' Capture 2: a
' Capture 3: short
' Capture 4: sentence
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = @"(\b(\w+)\W+)+";
string input = "This is a short sentence.";
Match match = Regex.Match(input, pattern);
Console.WriteLine("Match: {0}", match.Value);
for (int ctr = 1; ctr < match.Groups.Count; ctr++)
{
Console.WriteLine(" Group {0}: {1}", ctr, match.Groups[ctr].Value);
int capCtr = 0;
foreach (Capture capture in match.Groups[ctr].Captures)
{
Console.WriteLine(" Capture {0}: {1}", capCtr, capture.Value);
capCtr++;
}
}
}
}
// The example displays the following output:
// Match: This is a short sentence.
// Group 1: sentence.
// Capture 0: This
// Capture 1: is
// Capture 2: a
// Capture 3: short
// Capture 4: sentence.
// Group 2: sentence
// Capture 0: This
// Capture 1: is
// Capture 2: a
// Capture 3: short
// Capture 4: sentence
規則運算式模式 \b(\w+)\W+)+ 會從字串中擷取個別字組。 其定義方式如下表所示。
模式 |
描述 |
---|---|
\b |
開始字緣比對。 |
(\w+) |
比對一個或多個文字字元。 這些字元會共同形成一個字組。 這是第二個擷取群組。 |
\W+ |
比對一個或多個非文字字元。 |
(\w+)\W+)+ |
比對一或多個後面接一或多個非字組字元一或多次的字組字元模式。 這是第一個擷取群組。 |
第一個擷取群組會比對句子的每個字。 第二個擷取群組會比對每個字組與標點符號,以及字組織後的空格。 索引為 2 的 Group 物件會提供第二個擷取群組比對之文字的相關資訊。 擷取群組所擷取到的完整字組集可從 Group.Captures 屬性所傳回的 CaptureCollection 物件取得。