反向參考建構
反向參考提供便利的方式來識別字串內的重複字元或子字串。 例如,如果輸入字串包含多次出現的任意子字串,您可以比對第一個出現的子字串與擷取的群組,接著使用反向參考來比對隨後出現的子字串。
注意事項 |
---|
對於取代字串中的具名和編號擷取群組,會使用不同的語法用來參照。如需詳細資訊,請參閱替代。 |
.NET Framework 會定義個別的語言項目,以參考編號和具名的擷取群組。 如需擷取群組的詳細資訊,請參閱群組建構。
編號的反向參考
編號的反向參考會使用下列語法:
\number
其中 number 是規則運算式中的擷取群組序數位置。 例如,\4 會比對第四個擷取群組的內容。 如果 number 沒有在規則運算式模式中定義,便會發生剖析錯誤,而且規則運算式引擎會擲回 ArgumentException。 例如,規則運算式 \b(\w+)\s\1 有效,因為 (\w+) 是運算式中第一個和唯一的擷取群組。 另一方面,\b(\w+)\s\2 無效並擲回引數例外狀況,因為沒有編號為 \2 的擷取群組。
請注意,八進位逸出程式碼 (例如 \16 和 \number) 和使用相同標記法之反向參考間的模稜兩可。 這個模棱兩可的情況已解決,如下所示:
運算式 \1 到 \9 永遠解譯為反向參考,而不是八進位代碼。
如果多位數運算式的第一個數字是 8 或 9 (例如 \80 或 \91),該運算式便會被解譯為常值。
從 \10 到更大值的運算式會被視為反向參考 (如果沒有對應至該數字的反向參考),否則,它們會被解譯為八進位代碼。
如果規則運算式包含未定義之群組號碼的反向參考,便會發生剖析錯誤,規則運算式引擎會擲回 ArgumentException。
如果有模稜兩可的問題,您可以使用 \k< 名稱> 標記法,這樣不會模稜兩可,而且不會與八進位字元碼混淆。 同樣地,十六進位的代碼,例如 \xdd 不會模稜兩可,而且不會與反向參考混淆。
下列範例會在字串中尋找雙字組字元。 它會定義規則運算式 (\w)\1,由下列項目組成。
項目 |
描述 |
---|---|
(\w) |
比對字組字元,並將其指派給第一個擷取群組。 |
\1 |
比對與第一個擷取群組之值相同的下一個字元。 |
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim pattern As String = "(\w)\1"
Dim input As String = "trellis llama webbing dresser swagger"
For Each match As Match In Regex.Matches(input, pattern)
Console.WriteLine("Found '{0}' at position {1}.", _
match.Value, match.Index)
Next
End Sub
End Module
' The example displays the following output:
' Found 'll' at position 3.
' Found 'll' at position 8.
' Found 'bb' at position 16.
' Found 'ss' at position 25.
' Found 'gg' at position 33.
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = @"(\w)\1";
string input = "trellis llama webbing dresser swagger";
foreach (Match match in Regex.Matches(input, pattern))
Console.WriteLine("Found '{0}' at position {1}.",
match.Value, match.Index);
}
}
// The example displays the following output:
// Found 'll' at position 3.
// Found 'll' at position 8.
// Found 'bb' at position 16.
// Found 'ss' at position 25.
// Found 'gg' at position 33.
具名反向參考
具名的反向參考是使用下列語法來定義的:
\k<name>
或:
\k'name'
其中 name 是規則運算式模式中所定義的擷取群組的名稱。 如果在規則運算式模式中未定義 name,便會發生剖析錯誤,而且規則運算式引擎會擲回 ArgumentException。
下列範例會在字串中尋找雙字組字元。 它會定義規則運算式 (?<char>\w)\k<char>,由下列項目組成。
項目 |
描述 |
---|---|
(?<char>\w) |
比對字組字元,並將其指派給名為 char 的擷取群組。 |
\k<char> |
比對與 char 擷取群組之值相同的下一個字元。 |
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim pattern As String = "(?<char>\w)\k<char>"
Dim input As String = "trellis llama webbing dresser swagger"
For Each match As Match In Regex.Matches(input, pattern)
Console.WriteLine("Found '{0}' at position {1}.", _
match.Value, match.Index)
Next
End Sub
End Module
' The example displays the following output:
' Found 'll' at position 3.
' Found 'll' at position 8.
' Found 'bb' at position 16.
' Found 'ss' at position 25.
' Found 'gg' at position 33.
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = @"(?<char>\w)\k<char>";
string input = "trellis llama webbing dresser swagger";
foreach (Match match in Regex.Matches(input, pattern))
Console.WriteLine("Found '{0}' at position {1}.",
match.Value, match.Index);
}
}
// The example displays the following output:
// Found 'll' at position 3.
// Found 'll' at position 8.
// Found 'bb' at position 16.
// Found 'ss' at position 25.
// Found 'gg' at position 33.
請注意,該 name 也可以是數字的字串表示。 例如,下列範例會使用規則運算式 (?<2>\w)\k<2> 來尋找字串中的雙字組字元。
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim pattern As String = "(?<2>\w)\k<2>"
Dim input As String = "trellis llama webbing dresser swagger"
For Each match As Match In Regex.Matches(input, pattern)
Console.WriteLine("Found '{0}' at position {1}.", _
match.Value, match.Index)
Next
End Sub
End Module
' The example displays the following output:
' Found 'll' at position 3.
' Found 'll' at position 8.
' Found 'bb' at position 16.
' Found 'ss' at position 25.
' Found 'gg' at position 33.
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = @"(?<2>\w)\k<2>";
string input = "trellis llama webbing dresser swagger";
foreach (Match match in Regex.Matches(input, pattern))
Console.WriteLine("Found '{0}' at position {1}.",
match.Value, match.Index);
}
}
// The example displays the following output:
// Found 'll' at position 3.
// Found 'll' at position 8.
// Found 'bb' at position 16.
// Found 'ss' at position 25.
// Found 'gg' at position 33.
反向參考比對的項目
反向參考會參照群組最近使用的定義 (由左至右比對時,最接近左邊的定義)。 當群組進行多個擷取時,反向參考會參照最近發生的擷取。
以下範例包含規則運算式模式 (?<1>a)(?<1>\1b)*,此模式可重新定義 \ 1 具名群組。 下表說明規則運算式中的每個模式。
模式 |
描述 |
---|---|
(?<1>a) |
比對字元 "a",並將結果指派給名為 1 的擷取群組。 |
(?<1>\1b)* |
比對出現 0 或 1 次,名為 1 的群組連同 "b",並將結果指派至名為 1 的擷取群組。 |
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim pattern As String = "(?<1>a)(?<1>\1b)*"
Dim input As String = "aababb"
For Each match As Match In Regex.Matches(input, pattern)
Console.WriteLine("Match: " + match.Value)
For Each group As Group In match.Groups
Console.WriteLIne(" Group: " + group.Value)
Next
Next
End Sub
End Module
' The example display the following output:
' Group: aababb
' Group: abb
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = @"(?<1>a)(?<1>\1b)*";
string input = "aababb";
foreach (Match match in Regex.Matches(input, pattern))
{
Console.WriteLine("Match: " + match.Value);
foreach (Group group in match.Groups)
Console.WriteLine(" Group: " + group.Value);
}
}
}
// The example displays the following output:
// Group: aababb
// Group: abb
在比較規則運算式與輸入字串 ("aababb") 時,規則運算式引擎會執行下列作業:
它會從該字串的開頭開始,並成功地以運算式 (?<1>a) 比對 "a"。 1 群組的值現在是「a」。
它會前進到第二個字元,並且成功地比對字串 "ab" 與運算式 \1b,或是 "ab"。 然後它會將結果 "ab" 指派至 \1。
它會前進到第四個字元。 運算式 (?<1>\1b) 應比對零次以上,才能成功符合字串「abb」與運算式 \1b。 它會將結果 "abb" 指派回到 \1。
在此範例中,* 是迴圈數量詞,它會重複評估直到規則運算式引擎無法符合其所定義的模式為止。 迴圈數量詞並不會清除群組定義。
如果群組沒有擷取任何子字串,該群組的反向參考會是未定義的,而且從來不會比對。 這由定義如下的規則運算式模式 \b(\p{Lu}{2})(\d{2})?(\p{Lu}{2})\b 說明:
模式 |
描述 |
---|---|
\b |
開始字緣比對。 |
(\p{Lu}{2}) |
比對兩個大寫字母。 這是第一個擷取群組。 |
(\d{2})? |
比對出現零次或一次的兩個十進位數字。 這是第二個擷取群組。 |
(\p{Lu}{2}) |
比對兩個大寫字母。 這是第三個擷取群組。 |
\b |
結束字緣比對。 |
輸入的字串可以符合這個規則運算式,即使不存在第二個擷取群組所定義的兩個十進位數字也是如此。 下列範例顯示即使比對成功,仍會在兩個成功的擷取群組之間找到空的擷取群組。
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim pattern As String = "\b(\p{Lu}{2})(\d{2})?(\p{Lu}{2})\b"
Dim inputs() As String = { "AA22ZZ", "AABB" }
For Each input As String In inputs
Dim match As Match = Regex.Match(input, pattern)
If match.Success Then
Console.WriteLine("Match in {0}: {1}", input, match.Value)
If match.Groups.Count > 1 Then
For ctr As Integer = 1 To match.Groups.Count - 1
If match.Groups(ctr).Success Then
Console.WriteLine("Group {0}: {1}", _
ctr, match.Groups(ctr).Value)
Else
Console.WriteLine("Group {0}: <no match>", ctr)
End If
Next
End If
End If
Console.WriteLine()
Next
End Sub
End Module
' The example displays the following output:
' Match in AA22ZZ: AA22ZZ
' Group 1: AA
' Group 2: 22
' Group 3: ZZ
'
' Match in AABB: AABB
' Group 1: AA
' Group 2: <no match>
' Group 3: BB
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = @"\b(\p{Lu}{2})(\d{2})?(\p{Lu}{2})\b";
string[] inputs = { "AA22ZZ", "AABB" };
foreach (string input in inputs)
{
Match match = Regex.Match(input, pattern);
if (match.Success)
{
Console.WriteLine("Match in {0}: {1}", input, match.Value);
if (match.Groups.Count > 1)
{
for (int ctr = 1; ctr <= match.Groups.Count - 1; ctr++)
{
if (match.Groups[ctr].Success)
Console.WriteLine("Group {0}: {1}",
ctr, match.Groups[ctr].Value);
else
Console.WriteLine("Group {0}: <no match>", ctr);
}
}
}
Console.WriteLine();
}
}
}
// The example displays the following output:
// Match in AA22ZZ: AA22ZZ
// Group 1: AA
// Group 2: 22
// Group 3: ZZ
//
// Match in AABB: AABB
// Group 1: AA
// Group 2: <no match>
// Group 3: BB