正規表現の動作の詳細Details of Regular Expression Behavior

.NET Framework の正規表現エンジンはバックトラッキング型の正規表現マッチャーであり、Perl、Python、Emacs、および Tcl で使われているのと同じ従来型の非決定性有限オートマトン (NFA) エンジンを採用しています。The .NET Framework regular expression engine is a backtracking regular expression matcher that incorporates a traditional Nondeterministic Finite Automaton (NFA) engine such as that used by Perl, Python, Emacs, and Tcl. このエンジンは、awk、egrep、または lex に見られるような、より高速であるが制限が多い、純粋な正規表現決定性有限オートマトン (DFA) エンジンとは異なります。This distinguishes it from faster, but more limited, pure regular expression Deterministic Finite Automaton (DFA) engines such as those found in awk, egrep, or lex. また、標準化されているが低速な POSIX NFA とも異なります。This also distinguishes it from standardized, but slower, POSIX NFAs. 次のセクションでは、これら 3 種類の正規表現エンジンについて説明し、.NET Framework の正規表現が従来型 NFA エンジンを使って実装されている理由について説明します。The following section describes the three types of regular expression engines, and explains why regular expressions in the .NET Framework are implemented by using a traditional NFA engine.

NFA エンジンの利点Benefits of the NFA Engine

DFA エンジンがパターン一致を実行する場合、その処理順序は入力文字列によって決定されます。When DFA engines perform pattern matching, their processing order is driven by the input string. このエンジンは入力文字列の先頭で開始し、順番に進んで、次の文字が正規表現パターンと一致するかどうかを判断します。The engine begins at the beginning of the input string and proceeds sequentially to determine whether the next character matches the regular expression pattern. このエンジンでは、想定され得る最長の文字列を確実に検索できます。They can guarantee to match the longest string possible. 同じ文字が 2 回テストされることはないため、DFA エンジンはバックトラッキングをサポートしません。Because they never test the same character twice, DFA engines do not support backtracking. ただし、DFA エンジンには有限状態しか含まれないため、前方参照を使用してパターンを検索することはできません。また、明示的な展開が作成されないため、部分式をキャプチャできません。However, because a DFA engine contains only finite state, it cannot match a pattern with backreferences, and because it does not construct an explicit expansion, it cannot capture subexpressions.

DFA エンジンとは異なり、従来型 NFA エンジンがパターン一致を実行する場合、その処理順序は正規表現パターンによって決定されます。Unlike DFA engines, when traditional NFA engines perform pattern matching, their processing order is driven by the regular expression pattern. 特定の言語要素を処理するときに、エンジンは最長一致を使用します。つまり、できるだけ多くの入力文字列と一致するようにします。As it processes a particular language element, the engine uses greedy matching; that is, it matches as much of the input string as it possibly can. しかし、部分式の一致が見つかった後の状態も保存します。But it also saves its state after successfully matching a subexpression. 最終的に一致が見つからなかった場合、エンジンは保存した状態に戻ることができるため、さらに照合を試行できます。If a match eventually fails, the engine can return to a saved state so it can try additional matches. 正規表現の後の言語要素も照合できるようにするために、この見つかった部分式の一致を破棄するプロセスを "バックトラッキング" と呼びます。This process of abandoning a successful subexpression match so that later language elements in the regular expression can also match is known as backtracking. NFA エンジンは、バックトラッキングを使用して、ある正規表現で可能なすべての展開を特定の順序でテストし、最初に一致した文字列を採用します。NFA engines use backtracking to test all possible expansions of a regular expression in a specific order and accept the first match. 従来型 NFA エンジンでは、見つかった一致文字列の正規表現に固有の展開が作成されるため、部分式に一致する文字列と、一致する前方参照をキャプチャできます。Because a traditional NFA engine constructs a specific expansion of the regular expression for a successful match, it can capture subexpression matches and matching backreferences. しかし、従来型 NFA ではバックトラックが行われるため、1 つの状態に到達する経路が複数ある場合には、同じ状態に何度も到達する可能性があります。However, because a traditional NFA backtracks, it can visit the same state multiple times if it arrives at the state over different paths. その結果、最悪の場合には指数関数的に実行速度が遅くなることがあります。As a result, it can run exponentially slowly in the worst case. 従来型 NFA エンジンでは、最初に見つかった一致文字列が採用されるため、その他の (おそらく、より長い) 一致文字列が見つからないままになる場合もあります。Because a traditional NFA engine accepts the first match it finds, it can also leave other (possibly longer) matches undiscovered.

POSIX NFA エンジンは従来型 NFA エンジンと似ていますが、一致する最長の文字列が確実に見つかるまでバックトラックが継続される点が異なります。POSIX NFA engines are like traditional NFA engines, except that they continue to backtrack until they can guarantee that they have found the longest match possible. その結果、POSIX NFA エンジンは従来型 NFA エンジンよりも実行速度が遅くなります。また、POSIX NFA エンジンを使用する場合は、バックトラッキング検索の順序を変更して、より短い一致文字列を長い一致文字列よりも優先させることはできません。As a result, a POSIX NFA engine is slower than a traditional NFA engine, and when you use a POSIX NFA engine, you cannot favor a shorter match over a longer one by changing the order of the backtracking search.

従来型 NFA エンジンは、DFA エンジンや POSIX NFA エンジンよりも文字列の一致をより厳密に制御するため、プログラマに人気があります。Traditional NFA engines are favored by programmers because they offer greater control over string matching than either DFA or POSIX NFA engines. NFA エンジンは、最悪の場合には実行速度が遅くなることもありますが、あいまいさを少なくし、バックトラッキングを制限するパターンを使用すると、一致する文字列を線形時間または多項式時間で見つけるように調整できます。Although, in the worst case, they can run slowly, you can steer them to find matches in linear or polynomial time by using patterns that reduce ambiguities and limit backtracking. 言い換えると、NFA エンジンはパフォーマンスと引き換えに能力と柔軟性を向上させますが、ほとんどの場合、正規表現が適切に記述されていれば十分に許容できるパフォーマンスを実現でき、バックトラッキングによってパフォーマンスが指数関数的に低下する状況は回避されます。In other words, although NFA engines trade performance for power and flexibility, in most cases they offer good to acceptable performance if a regular expression is well-written and avoids cases in which backtracking degrades performance exponentially.

注意

過度なバックトラッキングによって発生するパフォーマンスの低下と、そのような問題を回避する正規表現の作成方法については、「バックトラッキング」をご覧ください。For information about the performance penalty caused by excessive backtracking and ways to craft a regular expression to work around them, see Backtracking.

.NET Framework エンジンの機能.NET Framework Engine Capabilities

従来型の NFA エンジンの長所を利用するために、.NET Framework の正規表現エンジンには、プログラマがバックトラッキング エンジンを調整できるようにするための構成体セットが組み込まれています。To take advantage of the benefits of a traditional NFA engine, the .NET Framework regular expression engine includes a complete set of constructs to enable programmers to steer the backtracking engine. それらの構成体を使用すると、高速検索を実行したり、他の展開よりも特定の展開を優先させたりできます。These constructs can be used to find matches faster or to favor specific expansions over others.

.NET Framework の正規表現エンジンのその他の機能は次のとおりです。Other features of the .NET Framework regular expression engine include the following:

  • 最短一致の量指定子: ??*?+?{n,m}?Lazy quantifiers: ??, *?, +?, {n,m}?. これらの構成体は、バックトラッキング エンジンに対し、繰り返しの回数が最も少ない文字列を最初に検索するように指示します。These constructs tell the backtracking engine to search the minimum number of repetitions first. 逆に、通常の最長一致の量指定子は、繰り返しの回数が最も多い文字列を最初に検索しようとします。In contrast, ordinary greedy quantifiers try to match the maximum number of repetitions first. 2 つの量指定子の動作の違いを次の例に示します。The following example illustrates the difference between the two. 正規表現は、数字で終わる文を照合し、キャプチャ グループはその数字を抽出します。A regular expression matches a sentence that ends in a number, and a capturing group is intended to extract that number. 正規表現 .+(\d+)\. には最長一致の量指定子 .+ が含まれます。これにより、正規表現エンジンは数字の最後の桁のみをキャプチャします。The regular expression .+(\d+)\. includes the greedy quantifier .+, which causes the regular expression engine to capture only the last digit of the number. 対照的に、正規表現 .+?(\d+)\. には最短一致の量指定子 .+? が含まれます。これにより、正規表現エンジンは数字全体をキャプチャします。In contrast, the regular expression .+?(\d+)\. includes the lazy quantifier .+?, which causes the regular expression engine to capture the entire number.

    using System;
    using System.Text.RegularExpressions;
    
    public class Example
    {
       public static void Main()
       {
          string greedyPattern = @".+(\d+)\.";
          string lazyPattern = @".+?(\d+)\.";
          string input = "This sentence ends with the number 107325.";
          Match match;
          
          // Match using greedy quantifier .+.
          match = Regex.Match(input, greedyPattern);
          if (match.Success)
             Console.WriteLine("Number at end of sentence (greedy): {0}", 
                               match.Groups[1].Value);
          else
             Console.WriteLine("{0} finds no match.", greedyPattern);
                 
          // Match using lazy quantifier .+?.
          match = Regex.Match(input, lazyPattern);
          if (match.Success)
             Console.WriteLine("Number at end of sentence (lazy): {0}", 
                               match.Groups[1].Value);
          else
             Console.WriteLine("{0} finds no match.", lazyPattern);
       }
    }
    // The example displays the following output:
    //       Number at end of sentence (greedy): 5
    //       Number at end of sentence (lazy): 107325
    
    Imports System.Text.RegularExpressions
    
    Module Example
       Public Sub Main()
          Dim greedyPattern As String = ".+(\d+)\."
          Dim lazyPattern As String = ".+?(\d+)\."
          Dim input As String = "This sentence ends with the number 107325."
          Dim match As Match
          
          ' Match using greedy quantifier .+.
          match = Regex.Match(input, greedyPattern)
          If match.Success Then
             Console.WriteLine("Number at end of sentence (greedy): {0}", 
                               match.Groups(1).Value)
          Else
             Console.WriteLine("{0} finds no match.", greedyPattern)
          End If
                 
          ' Match using lazy quantifier .+?.
          match = Regex.Match(input, lazyPattern)
          If match.Success Then
             Console.WriteLine("Number at end of sentence (lazy): {0}", 
                               match.Groups(1).Value)
          Else
             Console.WriteLine("{0} finds no match.", lazyPattern)
          End If
       End Sub
    End Module
    ' The example displays the following output:
    '       Number at end of sentence (greedy): 5
    '       Number at end of sentence (lazy): 107325
    

    この正規表現の最長一致バージョンと最短一致バージョンは、次の表に示すように定義されています。The greedy and lazy versions of this regular expression are defined as shown in the following table.`

    パターンPattern 説明Description
    .+ (最長一致の量指定子).+ (greedy quantifier) 任意の文字の 1 回以上の出現に一致します。Match at least one occurrence of any character. これにより、正規表現エンジンは文字列全体を照合してから、必要に応じてバックトラックし、パターンの残りの部分を照合します。This causes the regular expression engine to match the entire string, and then to backtrack as needed to match the remainder of the pattern.
    .+? (最短一致の量指定子).+? (lazy quantifier) 任意の文字の 1 回以上の出現 (ただし、可能な限り少ない回数) に一致します。Match at least one occurrence of any character, but match as few as possible.
    (\d+) 1 文字以上の数字と一致し、その文字を最初のキャプチャ グループに代入します。Match at least one numeric character, and assign it to the first capturing group.
    \. ピリオドと一致します。Match a period.

    最短一致の量指定子について詳しくは、「限定子」をご覧ください。For more information about lazy quantifiers, see Quantifiers.

  • 肯定先読み: (?=subexpression)Positive lookahead: (?=subexpression). この機能により、バックトラッキング エンジンは部分式と一致する文字列を見つけた後で、テキスト内の同じ位置に戻ることができます。This feature allows the backtracking engine to return to the same spot in the text after matching a subexpression. 同じ位置から開始する複数のパターンを確認してテキスト全体を検索する場合に便利です。It is useful for searching throughout the text by verifying multiple patterns that start from the same position. また、エンジンは、一致するテキストに部分文字列を含めずに、一致文字列の末尾に部分文字列が存在することを検証できます。It also allows the engine to verify that a substring exists at the end of the match without including the substring in the matched text. 次の例では、肯定先読みを使用して、後に区切り記号が続かない文中の単語を抽出します。The following example uses positive lookahead to extract the words in a sentence that are not followed by punctuation symbols.

    using System;
    using System.Text.RegularExpressions;
    
    public class Example
    {
       public static void Main()
       {
          string pattern = @"\b[A-Z]+\b(?=\P{P})";
          string input = "If so, what comes next?";
          foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
             Console.WriteLine(match.Value);
       }
    }
    // The example displays the following output:
    //       If
    //       what
    //       comes
    
    Imports System.Text.RegularExpressions
    
    Module Example
       Public Sub Main()
          Dim pattern As String = "\b[A-Z]+\b(?=\P{P})"
          Dim input As String = "If so, what comes next?"
          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:
    '       If
    '       what
    '       comes
    

    正規表現 \b[A-Z]+\b(?=\P{P}) は、次の表に示すように定義されています。The regular expression \b[A-Z]+\b(?=\P{P}) is defined as shown in the following table.

    パターンPattern 説明Description
    \b ワード境界から照合を開始します。Begin the match at a word boundary.
    [A-Z]+ 任意の英字と 1 回以上、一致します。Match any alphabetic character one or more times. Regex.Matches メソッドが RegexOptions.IgnoreCase オプションを使って呼び出されているため、比較では大文字と小文字が区別されません。Because the Regex.Matches method is called with the RegexOptions.IgnoreCase option, the comparison is case-insensitive.
    \b ワード境界で照合を終了します。End the match at a word boundary.
    (?=\P{P}) 先読みして次の文字が区切り記号かどうかを判定します。Look ahead to determine whether the next character is a punctuation symbol. 区切り記号でない場合は、一致と見なされます。If it is not, the match succeeds.

    肯定先読みアサーションについて詳しくは、「グループ化構成体」をご覧ください。For more information about positive lookahead assertions, see Grouping Constructs.

  • 否定先読み: (?!subexpression)Negative lookahead: (?!subexpression). この機能により、部分式に一致する文字列が見つからなかった場合にのみ、表現に一致できるようになります。This feature adds the ability to match an expression only if a subexpression fails to match. ある文字列を除外する表現の方が、含める表現よりも単純になることが多いため、この機能は検索を簡略化する場合に特に力を発揮します。This is particularly powerful for pruning a search, because it is often simpler to provide an expression for a case that should be eliminated than an expression for cases that must be included. たとえば、"non" で始まらない単語を表す表現を記述するのは簡単ではありません。For example, it is difficult to write an expression for words that do not begin with "non". 次の例では、否定先読みを使用してこれらを除外します。The following example uses negative lookahead to exclude them.

    using System;
    using System.Text.RegularExpressions;
    
    public class Example
    {
       public static void Main()
       {
          string pattern = @"\b(?!non)\w+\b";
          string input = "Nonsense is not always non-functional.";
          foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
             Console.WriteLine(match.Value);
       }
    }
    // The example displays the following output:
    //       is
    //       not
    //       always
    //       functional
    
    Imports System.Text.RegularExpressions
    
    Module Example
       Public Sub Main()
          Dim pattern As String = "\b(?!non)\w+\b"
          Dim input As String = "Nonsense is not always non-functional."
          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:
    '       is
    '       not
    '       always
    '       functional
    

    正規表現パターン \b(?!non)\w+\b は、次の表に示すように定義されています。The regular expression pattern \b(?!non)\w+\b is defined as shown in the following table.

    パターンPattern 説明Description
    \b ワード境界から照合を開始します。Begin the match at a word boundary.
    (?!non) 先読みして、現在の文字列が "non" で始まらないことを確認します。Look ahead to ensure that the current string does not begin with "non". "non" で始まる場合は、一致と見なされません。If it does, the match fails.
    (\w+) 1 つ以上の単語文字に一致します。Match one or more word characters.
    \b ワード境界で照合を終了します。End the match at a word boundary.

    否定先読みアサーションについて詳しくは、「グループ化構成体」をご覧ください。For more information about negative lookahead assertions, see Grouping Constructs.

  • 条件付き評価: (?(expression)yes|no) および(?(name)yes|no)。ここで、expression は照合する部分式、name はキャプチャ グループの名前、yes は、expression が一致するか、または name が空でない有効なキャプチャ グループである場合に照合する文字列、no は、expression が一致しないか、または name が空でない有効なキャプチャ グループではない場合に照合する部分式です。Conditional evaluation: (?(expression)yes|no) and (?(name)yes|no), where expression is a subexpression to match, name is the name of a capturing group, yes is the string to match if expression is matched or name is a valid, non-empty captured group, and no is the subexpression to match if expression is not matched or name is not a valid, non-empty captured group. この機能により、エンジンは直前の部分式の一致結果またはゼロ幅アサーションの結果に従って、複数の代替パターンを使用した検索を実行できます。This feature allows the engine to search by using more than one alternate pattern, depending on the result of a previous subexpression match or the result of a zero-width assertion. そのため、より強力な前方参照が可能になります。たとえば、直前の部分式が一致したかどうかに基づいて部分式を照合できます。This allows a more powerful form of backreference that permits, for example, matching a subexpression based on whether a previous subexpression was matched. 次の例の正規表現は、パブリック使用と内部使用の両方を目的とした段落と一致します。The regular expression in the following example matches paragraphs that are intended for both public and internal use. 内部使用のみを目的とした段落は <PRIVATE> タグで始まります。Paragraphs intended only for internal use begin with a <PRIVATE> tag. 正規表現パターン ^(?<Pvt>\<PRIVATE\>\s)?(?(Pvt)((\w+\p{P}?\s)+)|((\w+\p{P}?\s)+))\r?$ は、条件付き評価を使用して、パブリック使用と内部使用を目的とした段落の内容を別のキャプチャ グループに代入します。The regular expression pattern ^(?<Pvt>\<PRIVATE\>\s)?(?(Pvt)((\w+\p{P}?\s)+)|((\w+\p{P}?\s)+))\r?$ uses conditional evaluation to assign the contents of paragraphs intended for public and for internal use to separate capturing groups. これらの段落は、異なる方法で処理できます。These paragraphs can then be handled differently.

    using System;
    using System.Text.RegularExpressions;
    
    public class Example
    {
       public static void Main()
       {
          string input = "<PRIVATE> This is not for public consumption." + Environment.NewLine + 
                         "But this is for public consumption." + Environment.NewLine + 
                         "<PRIVATE> Again, this is confidential.\n";  
          string pattern = @"^(?<Pvt>\<PRIVATE\>\s)?(?(Pvt)((\w+\p{P}?\s)+)|((\w+\p{P}?\s)+))\r?$";
          string publicDocument = null, privateDocument = null;
          
          foreach (Match match in Regex.Matches(input, pattern, RegexOptions.Multiline))
          {
             if (match.Groups[1].Success) {
                privateDocument += match.Groups[1].Value + "\n";
             }
             else {
                publicDocument += match.Groups[3].Value + "\n";   
                privateDocument += match.Groups[3].Value + "\n";
             }  
          }
    
          Console.WriteLine("Private Document:");
          Console.WriteLine(privateDocument);
          Console.WriteLine("Public Document:");
          Console.WriteLine(publicDocument);
       }
    }
    // The example displays the following output:
    //    Private Document:
    //    This is not for public consumption.
    //    But this is for public consumption.
    //    Again, this is confidential.
    //    
    //    Public Document:
    //    But this is for public consumption.
    
    Imports System.Text.RegularExpressions
    
    Module Example
       Public Sub Main()
          Dim input As String = "<PRIVATE> This is not for public consumption." + vbCrLf + _
                                "But this is for public consumption." + vbCrLf + _
                                "<PRIVATE> Again, this is confidential." + vbCrLf
          Dim pattern As String = "^(?<Pvt>\<PRIVATE\>\s)?(?(Pvt)((\w+\p{P}?\s)+)|((\w+\p{P}?\s)+))\r?$"
          Dim publicDocument As String = Nothing
          Dim privateDocument As String = Nothing
          
          For Each match As Match In Regex.Matches(input, pattern, RegexOptions.Multiline)
             If match.Groups(1).Success Then
                privateDocument += match.Groups(1).Value + vbCrLf
             Else
                publicDocument += match.Groups(3).Value + vbCrLf   
                privateDocument += match.Groups(3).Value + vbCrLf
             End If  
          Next
    
          Console.WriteLine("Private Document:")
          Console.WriteLine(privateDocument)
          Console.WriteLine("Public Document:")
          Console.WriteLine(publicDocument)
       End Sub
    End Module
    ' The example displays the following output:
    '    Private Document:
    '    This is not for public consumption.
    '    But this is for public consumption.
    '    Again, this is confidential.
    '    
    '    Public Document:
    '    But this is for public consumption.
    

    正規表現パターンは、次の表に示すように定義されています。The regular expression pattern is defined as shown in the following table.

    パターンPattern 説明Description
    ^ 行の先頭から照合を開始します。Begin the match at the beginning of a line.
    (?<Pvt>\<PRIVATE\>\s)? 文字列 <PRIVATE> の後に空白文字が続くパターンの 0 回または 1 回の出現と一致します。Match zero or one occurrence of the string <PRIVATE> followed by a white-space character. 一致文字列を Pvt という名前のキャプチャ グループに代入します。Assign the match to a capturing group named Pvt.
    (?(Pvt)((\w+\p{P}?\s)+) Pvt キャプチャ グループが存在する場合は、1 個以上の単語文字の後に 0 個または 1 個の区切り記号と 1 つの空白文字が続くパターンの 1 回以上の出現と一致します。If the Pvt capturing group exists, match one or more occurrences of one or more word characters followed by zero or one punctuation separator followed by a white-space character. 部分文字列を最初のキャプチャ グループに代入します。Assign the substring to the first capturing group.
    |((\w+\p{P}?\s)+)) Pvt キャプチャ グループが存在しない場合は、1 個以上の単語文字の後に 0 個または 1 個の区切り記号と 1 つの空白文字が続くパターンの 1 回以上の出現と一致します。If the Pvt capturing group does not exist, match one or more occurrences of one or more word characters followed by zero or one punctuation separator followed by a white-space character. 部分文字列を 3 番目のキャプチャ グループに代入します。Assign the substring to the third capturing group.
    \r?$ 行末または文字列の末尾と一致します。Match the end of a line or the end of the string.

    条件付き評価について詳しくは、「代替構成体」をご覧ください。For more information about conditional evaluation, see Alternation Constructs.

  • グループ定義の均等化: (?<name1-name2> subexpression)Balancing group definitions: (?<name1-name2> subexpression). この機能により、正規表現エンジンは、かっこや左右の角かっこなどの入れ子になった構成体を追跡できます。This feature allows the regular expression engine to keep track of nested constructs such as parentheses or opening and closing brackets. 例については、「グループ化構成体」をご覧ください。For an example, see Grouping Constructs.

  • 非バックトラッキング部分式 (別名: 最長一致部分式): (?>subexpression)Nonbacktracking subexpressions (also known as greedy subexpressions): (?>subexpression). この機能により、バックトラッキング エンジンは、部分式と最初に一致した文字列だけを確実に検索できるようになります。この場合、表現は、部分式を含む表現とは関係ないように処理されます。This feature allows the backtracking engine to guarantee that a subexpression matches only the first match found for that subexpression, as if the expression were running independent of its containing expression. この構成体を使用しない場合は、より大きな表現によるバックトラッキング検索時に、部分式の動作が変化する可能性があります。If you do not use this construct, backtracking searches from the larger expression can change the behavior of a subexpression. たとえば、正規表現 (a+)\w は 1 つ以上の "a" 文字を、一連の "a" 文字に続く単語文字と共に照合し、一連の "a" 文字を最初のキャプチャ グループに代入します。ただし、入力文字列の最後の文字も "a" の場合は、\w 言語要素によって照合され、キャプチャ グループには含められません。For example, the regular expression (a+)\w matches one or more "a" characters, along with a word character that follows the sequence of "a" characters, and assigns the sequence of "a" characters to the first capturing group, However, if the final character of the input string is also an "a", it is matched by the \w language element and is not included in the captured group.

    using System;
    using System.Text.RegularExpressions;
    
    public class Example
    {
       public static void Main()
       {
          string[] inputs = { "aaaaa", "aaaaab" };
          string backtrackingPattern = @"(a+)\w";
          Match match;
    
          foreach (string input in inputs) {
             Console.WriteLine("Input: {0}", input);
             match = Regex.Match(input, backtrackingPattern);
             Console.WriteLine("   Pattern: {0}", backtrackingPattern);
             if (match.Success) { 
                Console.WriteLine("      Match: {0}", match.Value);
                Console.WriteLine("      Group 1: {0}", match.Groups[1].Value);
             }
             else {
                Console.WriteLine("      Match failed.");
             }   
          }
          Console.WriteLine();            
       }
    }
    // The example displays the following output:
    //       Input: aaaaa
    //          Pattern: (a+)\w
    //             Match: aaaaa
    //             Group 1: aaaa
    //       Input: aaaaab
    //          Pattern: (a+)\w
    //             Match: aaaaab
    //             Group 1: aaaaa
    
    Imports System.Text.RegularExpressions
    
    Module Example
       Public Sub Main()
          Dim inputs() As String = { "aaaaa", "aaaaab" }
          Dim backtrackingPattern As String = "(a+)\w"
          Dim match As Match
    
          For Each input As String In inputs
             Console.WriteLine("Input: {0}", input)
             match = Regex.Match(input, backtrackingPattern)
             Console.WriteLine("   Pattern: {0}", backtrackingPattern)
             If match.Success Then 
                Console.WriteLine("      Match: {0}", match.Value)
                Console.WriteLine("      Group 1: {0}", match.Groups(1).Value)
             Else 
                Console.WriteLine("      Match failed.")
             End If   
          Next
          Console.WriteLine()            
       End Sub
    End Module
    ' The example displays the following output:
    '       Input: aaaaa
    '          Pattern: (a+)\w
    '             Match: aaaaa
    '             Group 1: aaaa
    '       Input: aaaaab
    '          Pattern: (a+)\w
    '             Match: aaaaab
    '             Group 1: aaaaa
    

    正規表現 ((?>a+))\w では、この動作は回避されます。The regular expression ((?>a+))\w prevents this behavior. 連続するすべての "a" 文字はバックトラッキングなしで照合されるため、最初のキャプチャ グループにはすべての連続する "a" 文字が含まれます。Because all consecutive "a" characters are matched without backtracking, the first capturing group includes all consecutive "a" characters. "a" 文字の後に "a" 以外の文字が少なくとも 1 つ続かない場合は、一致と見なされません。If the "a" characters are not followed by at least one more character other than "a", the match fails.

    using System;
    using System.Text.RegularExpressions;
    
    public class Example
    {
       public static void Main()
       {
          string[] inputs = { "aaaaa", "aaaaab" };
          string nonbacktrackingPattern = @"((?>a+))\w";
          Match match;
    
          foreach (string input in inputs) {
             Console.WriteLine("Input: {0}", input);
             match = Regex.Match(input, nonbacktrackingPattern);
             Console.WriteLine("   Pattern: {0}", nonbacktrackingPattern);
             if (match.Success) { 
                Console.WriteLine("      Match: {0}", match.Value);
                Console.WriteLine("      Group 1: {0}", match.Groups[1].Value);
             }
             else {
                Console.WriteLine("      Match failed.");
             }   
          }
          Console.WriteLine();            
       }
    }
    // The example displays the following output:
    //       Input: aaaaa
    //          Pattern: ((?>a+))\w
    //             Match failed.
    //       Input: aaaaab
    //          Pattern: ((?>a+))\w
    //             Match: aaaaab
    //             Group 1: aaaaa
    
    Imports System.Text.RegularExpressions
    
    Module Example
       Public Sub Main()
          Dim inputs() As String = { "aaaaa", "aaaaab" }
          Dim nonbacktrackingPattern As String = "((?>a+))\w"
          Dim match As Match
    
          For Each input As String In inputs
             Console.WriteLine("Input: {0}", input)
             match = Regex.Match(input, nonbacktrackingPattern)
             Console.WriteLine("   Pattern: {0}", nonbacktrackingPattern)
             If match.Success Then 
                Console.WriteLine("      Match: {0}", match.Value)
                Console.WriteLine("      Group 1: {0}", match.Groups(1).Value)
             Else 
                Console.WriteLine("      Match failed.")
             End If   
          Next
          Console.WriteLine()            
       End Sub
    End Module
    ' The example displays the following output:
    '       Input: aaaaa
    '          Pattern: ((?>a+))\w
    '             Match failed.
    '       Input: aaaaab
    '          Pattern: ((?>a+))\w
    '             Match: aaaaab
    '             Group 1: aaaaa
    

    非バックトラッキング部分式について詳しくは、「グループ化構成体」をご覧ください。For more information about nonbacktracking subexpressions, see Grouping Constructs.

  • 右から左への一致。Regex クラス コンストラクターまたは静的インスタンス一致メソッドに RegexOptions.RightToLeft オプションを設定すると指定されます。Right-to-left matching, which is specified by supplying the RegexOptions.RightToLeft option to a Regex class constructor or static instance matching method. この機能は、左から右ではなく右から左に向かって検索する場合や、パターンの左側ではなく右側で検索を開始した方が効果的な場合に便利です。This feature is useful when searching from right to left instead of from left to right, or in cases where it is more efficient to begin a match at the right part of the pattern instead of the left. 次の例に示すように、右から左への一致を使用すると、最長一致の量指定子の動作を変更できます。As the following example illustrates, using right-to-left matching can change the behavior of greedy quantifiers. この例では、数字で終わる文に対して 2 つの検索を実行します。The example conducts two searches for a sentence that ends in a number. 最長一致の量指定子 + を使用する左から右への検索では、文中の 6 桁の数字の 1 つと一致しますが、右から左への検索では 6 桁の数字すべてと一致します。The left-to-right search that uses the greedy quantifier + matches one of the six digits in the sentence, whereas the right-to-left search matches all six digits. 正規表現パターンの説明については、このセクションで前に示した最短一致の量指定子の例を参照してください。For an description of the regular expression pattern, see the example that illustrates lazy quantifiers earlier in this section.

    using System;
    using System.Text.RegularExpressions;
    
    public class Example
    {
       public static void Main()
       {
          string greedyPattern = @".+(\d+)\.";
          string input = "This sentence ends with the number 107325.";
          Match match;
          
          // Match from left-to-right using lazy quantifier .+?.
          match = Regex.Match(input, greedyPattern);
          if (match.Success)
             Console.WriteLine("Number at end of sentence (left-to-right): {0}", 
                               match.Groups[1].Value);
          else
             Console.WriteLine("{0} finds no match.", greedyPattern);
          
          // Match from right-to-left using greedy quantifier .+.
          match = Regex.Match(input, greedyPattern, RegexOptions.RightToLeft);
          if (match.Success)
             Console.WriteLine("Number at end of sentence (right-to-left): {0}", 
                               match.Groups[1].Value);
          else
             Console.WriteLine("{0} finds no match.", greedyPattern);
       }
    }
    // The example displays the following output:
    //       Number at end of sentence (left-to-right): 5
    //       Number at end of sentence (right-to-left): 107325
    
    Imports System.Text.RegularExpressions
    
    Module Example
       Public Sub Main()
          Dim greedyPattern As String = ".+(\d+)\."
          Dim input As String = "This sentence ends with the number 107325."
          Dim match As Match
          
          ' Match from left-to-right using lazy quantifier .+?.
          match = Regex.Match(input, greedyPattern)
          If match.Success Then
             Console.WriteLine("Number at end of sentence (left-to-right): {0}", 
                               match.Groups(1).Value)
          Else
             Console.WriteLine("{0} finds no match.", greedyPattern)
          End If
          
          ' Match from right-to-left using greedy quantifier .+.
          match = Regex.Match(input, greedyPattern, RegexOptions.RightToLeft)
          If match.Success Then
             Console.WriteLine("Number at end of sentence (right-to-left): {0}", 
                               match.Groups(1).Value)
          Else
             Console.WriteLine("{0} finds no match.", greedyPattern)
          End If
       End Sub
    End Module
    ' The example displays the following output:
    '       Number at end of sentence (left-to-right): 5
    '       Number at end of sentence (right-to-left): 107325
    

    右から左への一致の詳細については、「正規表現のオプション」をご覧ください。For more information about right-to-left matching, see Regular Expression Options.

  • 肯定および否定後読み: 肯定後読みの場合は (?<=subexpression)、否定後読みの場合は (?<!subexpression)Positive and negative lookbehind: (?<=subexpression) for positive lookbehind, and (?<!subexpression) for negative lookbehind. この機能は、このトピックで前に説明した先読みと同様です。This feature is similar to lookahead, which is discussed earlier in this topic. 正規表現エンジンでは、完全な右から左への一致を実行できるため、正規表現では制限のない後読みが可能です。Because the regular expression engine allows complete right-to-left matching, regular expressions allow unrestricted lookbehinds. 肯定および否定後読みを使用して、入れ子になった部分式が外側の式のスーパーセットである場合に、入れ子の量指定子を回避することもできます。Positive and negative lookbehind can also be used to avoid nesting quantifiers when the nested subexpression is a superset of an outer expression. そのような入れ子の量指定子を使用した正規表現は、多くの場合にパフォーマンスを低下させます。Regular expressions with such nested quantifiers often offer poor performance. たとえば、次の例では、文字列が英数字で始まって英数字で終わること、および文字列内の他の文字がより大きなサブセットの 1 つであることを検証します。For example, the following example verifies that a string begins and ends with an alphanumeric character, and that any other character in the string is one of a larger subset. 電子メール アドレスの検証に使用される正規表現の一部になります。詳しくは、「方法:文字列が有効な電子メール形式であるかどうかを検証する」をご覧ください。It forms a portion of the regular expression used to validate email addresses; for more information, see How to: Verify that Strings Are in Valid Email Format.

    using System;
    using System.Text.RegularExpressions;
    
    public class Example
    {
       public static void Main()
       {
          string[] inputs = { "jack.sprat", "dog#", "dog#1", "me.myself", 
                              "me.myself!" };
          string pattern = @"^[A-Z0-9]([-!#$%&'.*+/=?^`{}|~\w])*(?<=[A-Z0-9])$";
          foreach (string input in inputs) {
             if (Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase))
                Console.WriteLine("{0}: Valid", input);
             else
                Console.WriteLine("{0}: Invalid", input);
          }
       }
    }
    // The example displays the following output:
    //       jack.sprat: Valid
    //       dog#: Invalid
    //       dog#1: Valid
    //       me.myself: Valid
    //       me.myself!: Invalid
    
    Imports System.Text.RegularExpressions
    
    Module Example
       Public Sub Main()
          Dim inputs() As String = { "jack.sprat", "dog#", "dog#1", "me.myself", 
                                     "me.myself!" }
          Dim pattern As String = "^[A-Z0-9]([-!#$%&'.*+/=?^`{}|~\w])*(?<=[A-Z0-9])$"
          For Each input As String In inputs
             If Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase) Then
                Console.WriteLine("{0}: Valid", input)
             Else
                Console.WriteLine("{0}: Invalid", input)
             End If   
          Next
       End Sub
    End Module
    ' The example displays the following output:
    '       jack.sprat: Valid
    '       dog#: Invalid
    '       dog#1: Valid
    '       me.myself: Valid
    '       me.myself!: Invalid
    

    正規表現 ^[A-Z0-9]([-!#$%&'.*+/=?^{}|~\w])*(?<=[A-Z0-9])$` は、次の表に示すように定義されています。The regular expression ^[A-Z0-9]([-!#$%&'.*+/=?^{}|~\w])*(?<=[A-Z0-9])$` is defined as shown in the following table.

    パターンPattern 説明Description
    ^ 文字列の先頭から照合を開始します。Begin the match at the beginning of the string.
    [A-Z0-9] 任意の数字または英数字と一致します。Match any numeric or alphanumeric character. (比較では、大文字と小文字を区別しません。)(The comparison is case-insensitive.)
    ([-!#$%&'.+/=?^`{}|~\w]) Match zero or more occurrences of any word character, or any of the following characters: -, !, #, $, %, &, ', ., *, +, /, =, ?, ^, `, {, }, |, or ~.
    (?<=[A-Z0-9]) 前の文字を後読みします。これは数字または英数字である必要があります。Look behind to the previous character, which must be numeric or alphanumeric. (比較では、大文字と小文字を区別しません。)(The comparison is case-insensitive.)
    $ 入力文字列の末尾で照合を終了します。End the match at the end of the string.

    肯定および否定後読みについて詳しくは、「グループ化構成体」をご覧ください。For more information about positive and negative lookbehind, see Grouping Constructs.

TitleTitle 説明Description
バックトラッキングBacktracking 正規表現のバックトラッキングを使用して、分岐処理によって別の一致を検索する方法について説明します。Provides information about how regular expression backtracking branches to find alternative matches.
コンパイルと再利用Compilation and Reuse パフォーマンスを向上させるための正規表現のコンパイルと再利用について説明します。Provides information about compiling and reusing regular expressions to increase performance.
スレッド セーフThread Safety 正規表現のスレッド セーフの詳細と、正規表現オブジェクトへのアクセスを同期することが必要なケースについて説明します。Provides information about regular expression thread safety and explains when you should synchronize access to regular expression objects.
.NET Framework 正規表現.NET Framework Regular Expressions 正規表現のプログラミング言語的な面の概要について説明します。Provides an overview of the programming language aspect of regular expressions.
正規表現のオブジェクト モデルThe Regular Expression Object Model 正規表現クラスの使用方法について詳しく説明し、コード例を示します。Provides information and code examples illustrating how to use the regular expression classes.
正規表現の例Regular Expression Examples 一般的なアプリケーションで正規表現を使用するときのコード例を示します。Contains code examples that illustrate the use of regular expressions in common applications.
正規表現言語 - クイック リファレンスRegular Expression Language - Quick Reference 正規表現の定義に使用できる一連の文字、演算子、および構成体について説明します。Provides information about the set of characters, operators, and constructs that you can use to define regular expressions.

関連項目Reference

System.Text.RegularExpressions