正規表現での前方参照コンストラクトBackreference Constructs in Regular Expressions

前方参照は、文字列内の繰り返しの文字または部分文字列を識別するために便利な方法を提供します。Backreferences provide a convenient way to identify a repeated character or substring within a string. たとえば、入力文字列に複数回出現する任意の部分文字列が含まれている場合は、キャプチャ グループを使用して最初の一致を検出し、前方参照を使用して部分文字列の後続の出現箇所を見つけます。For example, if the input string contains multiple occurrences of an arbitrary substring, you can match the first occurrence with a capturing group, and then use a backreference to match subsequent occurrences of the substring.

注意

別の構文を使用して、置換文字列内の名前付きおよび番号付きのキャプチャ グループを参照します。A separate syntax is used to refer to named and numbered capturing groups in replacement strings. 詳細については、「 置換」を参照してください。For more information, see Substitutions.

.NET では、番号付きおよび名前付きのキャプチャ グループを参照する個別の言語要素が定義されています。.NET defines separate language elements to refer to numbered and named capturing groups. キャプチャ グループの詳細については、「グループ化コンストラクト」を参照してください。For more information about capturing groups, see Grouping Constructs.

番号付き前方参照Numbered Backreferences

番号付き前方参照は、次の構文を使用します。A numbered backreference uses the following syntax:

\ number\ number

ここで、number は、正規表現でのキャプチャ グループの位置を表す序数です。where number is the ordinal position of the capturing group in the regular expression. たとえば、\4 は 4 番目のキャプチャ グループの内容と一致します。For example, \4 matches the contents of the fourth capturing group. number が正規表現パターンで定義されていない場合は、解析エラーが発生し、正規表現エンジンが ArgumentException をスローします。If number is not defined in the regular expression pattern, a parsing error occurs, and the regular expression engine throws an ArgumentException. たとえば、正規表現 \b(\w+)\s\1 は有効です ((\w+) が式の中の最初で唯一のキャプチャ グループであるため)。For example, the regular expression \b(\w+)\s\1 is valid, because (\w+) is the first and only capturing group in the expression. これに対して、\b(\w+)\s\2 は無効であり、引数の例外がスローされます (\2 という番号のキャプチャ グループは存在しないため)。On the other hand, \b(\w+)\s\2 is invalid and throws an argument exception, because there is no capturing group numbered \2. さらに、number が特定の序数位置のキャプチャ グループを示していても、そのキャプチャ グループにその序数位置とは異なる数値名が割り当てられている場合、正規表現パーサーで ArgumentException もスローされます。In addition, if number identifies a capturing group in a particular ordinal position, but that capturing group has been assigned a numeric name different than its ordinal position, the regular expression parser also throws an ArgumentException.

同じ表記法を使用した、8 進数のエスケープ コード (\16 など) と \number 前方参照との間には、あいまいさがあることに注意してください。Note the ambiguity between octal escape codes (such as \16) and \number backreferences that use the same notation. このあいまいさは、次のように解決されます。This ambiguity is resolved as follows:

  • \1 から \9 までの式は、8 進数コードとしてではなく、常に前方参照として解釈されます。The expressions \1 through \9 are always interpreted as backreferences, and not as octal codes.

  • 複数桁の式の最初の桁が 8 または 9 (\80\91) の場合、式はリテラルとして解釈されます。If the first digit of a multidigit expression is 8 or 9 (such as \80 or \91), the expression as interpreted as a literal.

  • \10 以降の式は、その番号に対応する前方参照がある場合、前方参照として解釈されます。それ以外の場合は、8 進数のコードとして解釈されます。Expressions from \10 and greater are considered backreferences if there is a backreference corresponding to that number; otherwise, they are interpreted as octal codes.

  • 正規表現に未定義のグループ番号への前方参照が含まれる場合、解析エラーが発生し、正規表現エンジンが ArgumentException をスローします。If a regular expression contains a backreference to an undefined group number, a parsing error occurs, and the regular expression engine throws an ArgumentException.

あいまいさが問題になる場合は、\k<name> という表記を使用できます。この表記はあいまいではなく、8 進数の文字コードと混同することはありません。If the ambiguity is a problem, you can use the \k<name> notation, which is unambiguous and cannot be confused with octal character codes. 同様に、\xdd などの 16 進数コードはあいまいではなく、前方参照と混同することはありません。Similarly, hexadecimal codes such as \xdd are unambiguous and cannot be confused with backreferences.

次の例では、文字列内の単語に使用される重複した文字を検索します。The following example finds doubled word characters in a string. 例で定義している正規表現 (\w)\1 は、次の要素で構成されています。It defines a regular expression, (\w)\1, which consists of the following elements.

要素Element 説明Description
(\w) 単語文字を検出し、最初のキャプチャ グループに割り当てます。Match a word character and assign it to the first capturing group.
\1 最初のキャプチャ グループの値と同じ次の文字を検出します。Match the next character that is the same as the value of the first capturing group.
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.
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.

名前付き前方参照Named Backreferences

名前付き前方参照は、次の構文を使用して定義します。A named backreference is defined by using the following syntax:

\k< name >\k< name >

またはor:

\k' name '\k' name '

ここで、name は正規表現パターンで定義されたキャプチャ グループの名前です。where name is the name of a capturing group defined in the regular expression pattern. name が正規表現パターンで定義されていない場合は、解析エラーが発生し、正規表現エンジンが ArgumentException をスローします。If name is not defined in the regular expression pattern, a parsing error occurs, and the regular expression engine throws an ArgumentException.

次の例では、文字列内の単語に使用される重複した文字を検索します。The following example finds doubled word characters in a string. 例で定義している正規表現 (?<char>\w)\k<char> は、次の要素で構成されています。It defines a regular expression, (?<char>\w)\k<char>, which consists of the following elements.

要素Element 説明Description
(?<char>\w) 単語文字を検出し、char という名前のキャプチャ グループに割り当てます。Match a word character and assign it to a capturing group named char.
\k<char> char キャプチャ グループの値と同じ次の文字を検出します。Match the next character that is the same as the value of the char capturing group.
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.
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.

名前付き数値前方参照Named numeric backreferences

\k を使用する名前付き前方参照の場合、name は数字の文字列表現にすることもできます。In a named backreference with \k, name can also be the string representation of a number. たとえば、次の例では正規表現 (?<2>\w)\k<2> を使用して、文字列内の単語の重複した文字を検索します。For example, the following example uses the regular expression (?<2>\w)\k<2> to find doubled word characters in a string. この例では、明示的に "2" という名前が付けられたキャプチャ グループを定義し、これに応じて、前方参照には "2" という名前が付けられています。In this case, the example defines a capturing group that is explicitly named "2", and the backreference is correspondingly named "2".

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.
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.

name が数字の文字列表現で、その名前を持つキャプチャ グループが存在しない場合、\k<name> は前方参照 \number と同じになります。ここで、number はキャプチャの序数位置です。If name is the string representation of a number, and no capturing group has that name, \k<name> is the same as the backreference \number, where number is the ordinal position of the capture. 次の例には、char という名前の単一のキャプチャ グループがあります。In the following example, there is a single capturing group named char. 前方参照構成体ではこれを \k<1> と呼びます。The backreference construct refers to it as \k<1>. 例からの出力に示されているように、char は最初のキャプチャ グループであるため、Regex.IsMatch の呼び出しは正常に行われています。As the output from the example shows, the call to the Regex.IsMatch succeeds because char is the first capturing group.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      Console.WriteLine(Regex.IsMatch("aa", @"(?<char>\w)\k<1>"));    
      // Displays "True".
   }
}


Imports System.Text.RegularExpressions

Module Example
   Public Sub Main()
      Console.WriteLine(Regex.IsMatch("aa", "(?<char>\w)\k<1>"))    
      ' Displays "True".
   End Sub
End Module

ただし、name が数字の文字列表現であり、その位置のキャプチャ グループに数値名が明示的に割り当てられている場合、正規表現パーサーではその序数位置でキャプチャ グループを識別することはできません。However, if name is the string representation of a number and the capturing group in that position has been explicitly assigned a numeric name, the regular expression parser cannot identify the capturing group by its ordinal position. 代わりに、ArgumentException がスローされます。Instead, it throws an ArgumentException. 次の例の唯一のキャプチャ グループには "2" という名前が付けられています。The only capturing group in the following example is named "2". \k コンストラクトが "1" という名前の前方参照を定義するために使用されているため、正規表現パーサーは最初のキャプチャ グループを識別できず、例外をスローします。Because the \k construct is used to define a backreference named "1", the regular expression parser is unable to identify the first capturing group and throws an exception.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      Console.WriteLine(Regex.IsMatch("aa", @"(?<2>\w)\k<1>"));    
      // Throws an ArgumentException.
   }
}


Imports System.Text.RegularExpressions

Module Example
   Public Sub Main()
      Console.WriteLine(Regex.IsMatch("aa", "(?<2>\w)\k<1>"))    
      ' Throws an ArgumentException.
   End Sub
End Module

前方参照と一致する内容What Backreferences Match

前方参照は、グループの最新の定義 (左から右に検出する場合は、すぐ左にある定義) を参照します。A backreference refers to the most recent definition of a group (the definition most immediately to the left, when matching left to right). 1 つのグループで複数のキャプチャが発生した場合、前方参照は最新のキャプチャを参照します。When a group makes multiple captures, a backreference refers to the most recent capture.

次の例には、正規表現パターン (?<1>a)(?<1>\1b)* が含まれています。このパターンは \1 の名前付きグループを再定義します。The following example includes a regular expression pattern, (?<1>a)(?<1>\1b)*, which redefines the \1 named group. 正規表現の各パターンは、次の表に示すように定義されています。The following table describes each pattern in the regular expression.

パターンPattern 説明Description
(?<1>a) 文字 "a" を検出し、結果を 1 という名前のキャプチャ グループに割り当てます。Match the character "a" and assign the result to the capturing group named 1.
(?<1>\1b)* 1 という名前のグループの 0 個以上の出現箇所を "b" と共に検出し、結果を 1 という名前のキャプチャ グループに割り当てます。Match zero or more occurrences of the group named 1 along with a "b", and assign the result to the capturing group named 1.
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
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

正規表現を入力文字列 ("aababb") と比較する際、正規表現エンジンは次の操作を実行します。In comparing the regular expression with the input string ("aababb"), the regular expression engine performs the following operations:

  1. 文字列の先頭から開始し、式 (?<1>a) で "a" を検出します。It starts at the beginning of the string, and successfully matches "a" with the expression (?<1>a). グループ 1 の値が "a" になります。The value of the 1 group is now "a".

  2. 次の文字に進み、式 \1b で文字列 "ab" を検出します。It advances to the second character, and successfully matches the string "ab" with the expression \1b, or "ab". 次に、その結果 "ab" を \1 に割り当てます。It then assigns the result, "ab" to \1.

  3. これにより 4 番目の文字に進みます。It advances to the fourth character. (?<1>\1b)* を 0 回以上照合し、式 \1b で文字列 "abb" を検出します。The expression (?<1>\1b)* is to be matched zero or more times, so it successfully matches the string "abb" with the expression \1b. その結果 "abb" を \1 に割り当てます。It assigns the result, "abb", back to \1.

この例では、* はループ量指定子であり、正規表現エンジンが定義したパターンを照合できなくなるまで、繰り返し評価されます。In this example, * is a looping quantifier -- it is evaluated repeatedly until the regular expression engine cannot match the pattern it defines. ループ量指定子によってグループの定義はクリアされません。Looping quantifiers do not clear group definitions.

グループで部分文字列がキャプチャされなかった場合、そのグループへの前方参照は未定義になり、一致することはありません。If a group has not captured any substrings, a backreference to that group is undefined and never matches. 次のように定義されている正規表現パターン \b(\p{Lu}{2})(\d{2})?(\p{Lu}{2})\b を例として示します。This is illustrated by the regular expression pattern \b(\p{Lu}{2})(\d{2})?(\p{Lu}{2})\b, which is defined as follows:

パターンPattern 説明Description
\b ワード境界から照合を開始します。Begin the match on a word boundary.
(\p{Lu}{2}) 2 つの大文字と一致します。Match two uppercase letters. これが最初のキャプチャ グループです。This is the first capturing group.
(\d{2})? 2 桁の 10 進数の 0 回または 1 回の出現と一致します。Match zero or one occurrence of two decimal digits. これが 2 番目のキャプチャ グループです。This is the second capturing group.
(\p{Lu}{2}) 2 つの大文字と一致します。Match two uppercase letters. これが 3 番目のキャプチャ グループです。This is the third capturing group.
\b ワード境界で照合を終了します。End the match on a word boundary.

2 番目のキャプチャ グループによって定義されている 2 桁の 10 進数が存在しない場合でも、入力文字列はこの正規表現を照合できます。An input string can match this regular expression even if the two decimal digits that are defined by the second capturing group are not present. 次の例では、一致が見つかった場合でも、成功した 2 つのキャプチャ グループの間に空のキャプチャ グループが検出されます。The following example shows that even though the match is successful, an empty capturing group is found between two successful capturing groups.

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
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

関連項目See also