кванторы в регулярных выраженияхQuantifiers in Regular Expressions

Квантификаторы определяют количество экземпляров символа, группы или класса символов, которое должно присутствовать во входных данных, чтобы было зафиксировано совпадение.Quantifiers specify how many instances of a character, group, or character class must be present in the input for a match to be found. В приведенной ниже таблице перечислены квантификаторы, поддерживаемые платформой .NET.The following table lists the quantifiers supported by .NET.

Жадный квантификаторGreedy quantifier Ленивый квантификаторLazy quantifier ОписаниеDescription
* *? Совпадение ноль или несколько раз.Match zero or more times.
+ +? Совпадение один или несколько раз.Match one or more times.
? ?? Совпадение ноль или один раз.Match zero or one time.
{ n }{ n } { n }?{ n }? Совпадение ровно n раз.Match exactly n times.
{ n ,}{ n ,} { n ,}?{ n ,}? Совпадение как минимум n раз.Match at least n times.
{ n , m }{ n , m } { n , m }?{ n , m }? Совпадение от n до m раз.Match from n to m times.

Количества n и m являются целочисленными константами.The quantities n and m are integer constants. Обычно квантификаторы "жадные" — они заставляют обработчик регулярных выражений выделить максимально возможное число вхождений определенного шаблона.Ordinarily, quantifiers are greedy; they cause the regular expression engine to match as many occurrences of particular patterns as possible. Добавление символа ? в квантификатор делает его отложенным (или ленивым). Это приводит к тому, что обработчик регулярных выражений пытается сопоставить так мало вхождений, как это возможно.Appending the ? character to a quantifier makes it lazy; it causes the regular expression engine to match as few occurrences as possible. Полное описание различий между "жадными" и "ленивыми" квантификаторами см. в разделе Жадные и ленивые квантификаторы далее в этой статье.For a complete description of the difference between greedy and lazy quantifiers, see the section Greedy and Lazy Quantifiers later in this topic.

Важно!

Вложенные квантификаторы (например, шаблон регулярного выражения (a*)*) могут увеличить количество сравнений, которые должен выполнять обработчик регулярных выражений, как экспоненциальная функция количества символов во входной строке.Nesting quantifiers (for example, as the regular expression pattern (a*)* does) can increase the number of comparisons that the regular expression engine must perform, as an exponential function of the number of characters in the input string. Дополнительные сведения об этом поведении и способах его обхода см. в статье о поиске с возвратом.For more information about this behavior and its workarounds, see Backtracking.

Квантификаторы регулярных выраженийRegular Expression Quantifiers

В следующих разделах перечислены квантификаторы, поддерживаемые регулярными выражениями платформы .NET.The following sections list the quantifiers supported by .NET regular expressions.

Примечание

Если в шаблоне регулярных выражений встречаются символы *, +, ?, { или }, обработчик регулярных выражений интерпретирует их как квантификаторы или как часть конструкций квантификаторов, если они не включены в класс символов.If the *, +, ?, {, and } characters are encountered in a regular expression pattern, the regular expression engine interprets them as quantifiers or part of quantifier constructs unless they are included in a character class. Чтобы они интерпретировались как символы-литералы за пределами класса символов, необходимо ставить перед ними escape-символ — обратную косую черту.To interpret these as literal characters outside a character class, you must escape them by preceding them with a backslash. Например, строка \* в шаблоне регулярного выражения интерпретируется как литеральный символ звездочки ("*").For example, the string \* in a regular expression pattern is interpreted as a literal asterisk ("*") character.

Совпадение ноль или несколько раз: *Match Zero or More Times: *

Квалификатор * выделяет предыдущий элемент, повторяющийся ноль или более раз.The * quantifier matches the preceding element zero or more times. Это свойство эквивалентно квантификатору {0,}.It is equivalent to the {0,} quantifier. * — жадный квантификатор, ленивым эквивалентом которого является квантификатор *?.* is a greedy quantifier whose lazy equivalent is *?.

В следующем примере показано, как использовать это регулярное выражение.The following example illustrates this regular expression. Пять из девяти чисел в исходной строке соответствуют заданному шаблону, а четыре числа (95, 929, 9219 и 9919) — нет.Of the nine digit groups in the input string, five match the pattern and four (95, 929, 9219, and 9919) do not.

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("'{0}' found at position {1}.", match.Value, 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.

Шаблон регулярного выражения определяется, как показано в следующей таблице.The regular expression pattern is defined as shown in the following table.

ШаблонPattern ОписаниеDescription
\b Начало на границе слова.Start at a word boundary.
91* Совпадение с символом "9", за которыми следует ноль или более символов "1".Match a "9" followed by zero or more "1" characters.
9* Выделить ноль или больше символов "9".Match zero or more "9" characters.
\b Конец на границе слова.End at a word boundary.

Совпадение один или несколько раз: +Match One or More Times: +

Квантификатор + сопоставляет предыдущий элемент один или несколько раз.The + quantifier matches the preceding element one or more times. Он эквивалентен {1,}.It is equivalent to {1,}. + — жадный квантификатор, ленивым эквивалентом которого является квантификатор +?.+ is a greedy quantifier whose lazy equivalent is +?.

Например, с помощью регулярного выражения \ban+\w*?\b осуществляется сопоставление целых слов, начинающихся с буквы a, за которой следует одна или несколько букв n.For example, the regular expression \ban+\w*?\b tries to match entire words that begin with the letter a followed by one or more instances of the letter n. В следующем примере показано, как использовать это регулярное выражение.The following example illustrates this regular expression. Регулярное выражение соответствует словам an, annual, announcement и antique и не соответствует словам autumn и all.The regular expression matches the words an, annual, announcement, and antique, and correctly fails to match autumn and all.

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("'{0}' found at position {1}.", match.Value, 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.      

Шаблон регулярного выражения определяется, как показано в следующей таблице.The regular expression pattern is defined as shown in the following table.

ШаблонPattern ОписаниеDescription
\b Начало на границе слова.Start at a word boundary.
an+ Совпадение с "a"с последующим одним или несколькими символами "n".Match an "a" followed by one or more "n" characters.
\w*? Совпадение со словообразующим символом ноль или несколько раз (по возможности минимальное количество раз).Match a word character zero or more times, but as few times as possible.
\b Конец на границе слова.End at a word boundary.

Совпадение ноль или один раз: ?Match Zero or One Time: ?

Квантификатор ? сопоставляет предыдущий элемент ноль или один раз.The ? quantifier matches the preceding element zero or one time. Он эквивалентен {0,1}.It is equivalent to {0,1}. ? — жадный квантификатор, ленивым эквивалентом которого является квантификатор ??.? is a greedy quantifier whose lazy equivalent is ??.

Например, с помощью регулярного выражения \ban?\b осуществляется сопоставление целых слов, начинающихся с буквы a, за которой следует одна буква n или не следует ни одной такой буквы.For example, the regular expression \ban?\b tries to match entire words that begin with the letter a followed by zero or one instances of the letter n. Иными словами, предпринимается попытка найти слова a и an.In other words, it tries to match the words a and an. В следующем примере показано, как использовать это регулярное выражение.The following example illustrates this regular expression.

string pattern = @"\ban?\b";
string input = "An amiable animal with a large snount and an animated nose.";
foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
   Console.WriteLine("'{0}' found at position {1}.", match.Value, 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 snount 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.

Шаблон регулярного выражения определяется, как показано в следующей таблице.The regular expression pattern is defined as shown in the following table.

ШаблонPattern ОписаниеDescription
\b Начало на границе слова.Start at a word boundary.
an? Совпадение с "a"с последующими символами "n" (при их наличии).Match an "a" followed by zero or one "n" character.
\b Конец на границе слова.End at a word boundary.

Совпадение ровно n раз: {n}Match Exactly n Times: {n}

Квантификатор {n} сопоставляет предыдущий элемент ровно n раз, где n — любое целое число.The {n} quantifier matches the preceding element exactly n times, where n is any integer. {n} — жадный квантификатор, ленивым эквивалентом которого является квантификатор {n}?.{n} is a greedy quantifier whose lazy equivalent is {n}?.

Например, с помощью регулярного выражения \b\d+\,\d{3}\b осуществляется поиск границы слова, за которой следует один или более десятичных знаков, еще три десятичных знака и граница слова.For example, the regular expression \b\d+\,\d{3}\b tries to match a word boundary followed by one or more decimal digits followed by three decimal digits followed by a word boundary. В следующем примере показано, как использовать это регулярное выражение.The following example illustrates this regular expression.

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("'{0}' found at position {1}.", match.Value, 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.

Шаблон регулярного выражения определяется, как показано в следующей таблице.The regular expression pattern is defined as shown in the following table.

ШаблонPattern ОписаниеDescription
\b Начало на границе слова.Start at a word boundary.
\d+ Совпадение с одной или несколькими десятичными цифрами.Match one or more decimal digits.
\, Совпадение с символом запятой.Match a comma character.
\d{3} Совпадение с тремя десятичными цифрами.Match three decimal digits.
\b Конец на границе слова.End at a word boundary.

Совпадение как минимум n раз: {n,}Match at Least n Times: {n,}

Квантификатор {n,} сопоставляет предыдущий элемент как минимум n раз, где n — любое целое число.The {n,} quantifier matches the preceding element at least n times, where n is any integer. {n,} — жадный квантификатор, ленивым эквивалентом которого является квантификатор {n,}?.{n,} is a greedy quantifier whose lazy equivalent is {n,}?.

Например, с помощью регулярного выражения \b\d{2,}\b\D+ осуществляется поиск границы слова, за которой следует по крайней мере два десятичных знака, граница слова и знак, не являющийся числом.For example, the regular expression \b\d{2,}\b\D+ tries to match a word boundary followed by at least two digits followed by a word boundary and a non-digit character. В следующем примере показано, как использовать это регулярное выражение.The following example illustrates this regular expression. Это регулярное выражение не соответствует фразе "7 days", так как она содержит всего одну десятичную цифру, но соответствует фразам "10 weeks and 300 years".The regular expression fails to match the phrase "7 days" because it contains just one decimal digit, but it successfully matches the phrases "10 weeks and 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("'{0}' found at position {1}.", match.Value, 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.

Шаблон регулярного выражения определяется, как показано в следующей таблице.The regular expression pattern is defined as shown in the following table.

ШаблонPattern ОписаниеDescription
\b Начало на границе слова.Start at a word boundary.
\d{2,} Совпадение как минимум с двумя десятичными цифрами.Match at least two decimal digits.
\b Соответствует границе слова.Match a word boundary.
\D+ Совпадение как минимум с одной цифрой, не являющейся десятичной.Match at least one non-decimal digit.

Совпадение от n до m раз: {n,m}Match Between n and m Times: {n,m}

Квантификатор {n,m} сопоставляет предыдущий элемент минимум n раз, но не больше m раз, где n и m — целые числа.The {n,m} quantifier matches the preceding element at least n times, but no more than m times, where n and m are integers. {n,m} — жадный квантификатор, ленивым эквивалентом которого является квантификатор {n,m}?.{n,m} is a greedy quantifier whose lazy equivalent is {n,m}?.

В следующем примере с помощью регулярного выражения (00\s){2,4} осуществляется поиск от двух до четырех вхождений двух нулей, за которыми следует пробел.In the following example, the regular expression (00\s){2,4} tries to match between two and four occurrences of two zero digits followed by a space. Обратите внимание, что в конце входной строки имеются пять вхождений этого фрагмента при максимуме в четыре вхождения.Note that the final portion of the input string includes this pattern five times rather than the maximum of four. Однако только начало этой части строки (до пробела и пятой пары нулей) соответствует шаблону регулярного выражения.However, only the initial portion of this substring (up to the space and the fifth pair of zeros) matches the regular expression pattern.

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("'{0}' found at position {1}.", match.Value, 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.

Совпадение ноль или несколько раз (ленивое совпадение): *?Match Zero or More Times (Lazy Match): *?

Квантификатор *? сопоставляет предыдущий элемент ноль или несколько раз, но как можно меньшее число раз.The *? quantifier matches the preceding element zero or more times, but as few times as possible. Это ленивый квантификатор, являющийся аналогом жадного квантификатора *.It is the lazy counterpart of the greedy quantifier *.

В следующем примере регулярное выражение \b\w*?oo\w*?\b сопоставляет все слова, которые содержат строку oo.In the following example, the regular expression \b\w*?oo\w*?\b matches all words that contain the string 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("'{0}' found at position {1}.", match.Value, 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.

Шаблон регулярного выражения определяется, как показано в следующей таблице.The regular expression pattern is defined as shown in the following table.

ШаблонPattern ОписаниеDescription
\b Начало на границе слова.Start at a word boundary.
\w*? Совпадение с нулем или минимально возможным числом словообразующих символов.Match zero or more word characters, but as few characters as possible.
oo Совпадение со строкой "oo".Match the string "oo".
\w*? Совпадение с нулем или минимально возможным числом словообразующих символов.Match zero or more word characters, but as few characters as possible.
\b Конец на границе слова.End on a word boundary.

Совпадение один или несколько раз (ленивое совпадение): +?Match One or More Times (Lazy Match): +?

Квантификатор +? сопоставляет предыдущий элемент один или более раз, но как можно меньшее число раз.The +? quantifier matches the preceding element one or more times, but as few times as possible. Это ленивый квантификатор, являющийся аналогом жадного квантификатора +.It is the lazy counterpart of the greedy quantifier +.

Например, регулярное выражение \b\w+?\b соответствует одному или нескольким символам, разделенным границами слов.For example, the regular expression \b\w+?\b matches one or more characters separated by word boundaries. В следующем примере показано, как использовать это регулярное выражение.The following example illustrates this regular expression.

string pattern = @"\b\w+?\b";
string input = "Aa Bb Cc Dd Ee Ff";
foreach (Match match in Regex.Matches(input, pattern))
   Console.WriteLine("'{0}' found at position {1}.", match.Value, 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.

Совпадение ноль или один раз (ленивое совпадение): ??Match Zero or One Time (Lazy Match): ??

Квантификатор ?? сопоставляет предыдущий элемент ноль или один раз, но как можно меньшее число раз.The ?? quantifier matches the preceding element zero or one time, but as few times as possible. Это ленивый квантификатор, являющийся аналогом жадного квантификатора ?.It is the lazy counterpart of the greedy quantifier ?.

Например, регулярное выражение ^\s*(System.)??Console.Write(Line)??\(?? пытается сопоставить строки "Console.Write" или "Console.WriteLine".For example, the regular expression ^\s*(System.)??Console.Write(Line)??\(?? attempts to match the strings "Console.Write" or "Console.WriteLine". Строка может также включать "System."The string can also include "System." перед "Console", за ней может следовать открывающая скобка.before "Console", and it can be followed by an opening parenthesis. Искомый текст должен находиться в начале строки, хотя перед ним может стоять пробел.The string must be at the beginning of a line, although it can be preceded by white space. В следующем примере показано, как использовать это регулярное выражение.The following example illustrates this regular expression.

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("'{0}' found at position {1}.", match.Value, 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.

Шаблон регулярного выражения определяется, как показано в следующей таблице.The regular expression pattern is defined as shown in the following table.

ШаблонPattern ОписаниеDescription
^ Соответствует концу входной строки.Match the start of the input stream.
\s* Соответствует нулю или нескольким символам пробела.Match zero or more white-space characters.
(System.)?? Совпадение с нулевым или единичным вхождением строки "System.".Match zero or one occurrence of the string "System.".
Console.Write Совпадение со строкой "Console.Write".Match the string "Console.Write".
(Line)?? Совпадение с нулевым или единичным вхождением строки "Line".Match zero or one occurrence of the string "Line".
\(?? Совпадение с нулем или одним экземпляром открывающих круглых скобок.Match zero or one occurrence of the opening parenthesis.

Совпадение ровно n раз (ленивое совпадение): {n}?Match Exactly n Times (Lazy Match): {n}?

Квантификатор {n}? сопоставляет предыдущий элемент ровно n раз, где n — любое целое число.The {n}? quantifier matches the preceding element exactly n times, where n is any integer. Это ленивый квантификатор, являющийся аналогом жадного квантификатора {n}.It is the lazy counterpart of the greedy quantifier {n}.

В следующем примере регулярное выражение \b(\w{3,}?\.){2}?\w{3,}?\b используется для определения адреса веб-сайта.In the following example, the regular expression \b(\w{3,}?\.){2}?\w{3,}?\b is used to identify a Web site address. Обратите внимание, что есть совпадение с "www.microsoft.com" и "msdn.microsoft.com", но нет совпадения с "mywebsite" или "mycompany.com".Note that it matches "www.microsoft.com" and "msdn.microsoft.com", but does not match "mywebsite" or "mycompany.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("'{0}' found at position {1}.", match.Value, 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.

Шаблон регулярного выражения определяется, как показано в следующей таблице.The regular expression pattern is defined as shown in the following table.

ШаблонPattern ОписаниеDescription
\b Начало на границе слова.Start at a word boundary.
(\w{3,}?\.) Совпадение с минимум тремя словообразующими символами как можно меньшее количество раз, зак которыми следует символ точки.Match at least 3 word characters, but as few characters as possible, followed by a dot or period character. Это первая группа записи.This is the first capturing group.
(\w{3,}?\.){2}? Совпадение с шаблоном в первой группе два раза, но как можно меньшее количество раз.Match the pattern in the first group two times, but as few times as possible.
\b Сопоставление заканчивается на границе слова.End the match on a word boundary.

Совпадение как минимум n раз (ленивое совпадение): {n,}?Match at Least n Times (Lazy Match): {n,}?

Квантификатор {n,}? сопоставляет предыдущий элемент как минимум n раз (где n — любое целое число), но как можно меньшее количество раз.The {n,}? quantifier matches the preceding element at least n times, where n is any integer, but as few times as possible. Это ленивый квантификатор, являющийся аналогом жадного квантификатора {n,}.It is the lazy counterpart of the greedy quantifier {n,}.

Его поведение приводится в описании квантификатора {n}? в предыдущем разделе.See the example for the {n}? quantifier in the previous section for an illustration. В регулярном выражении из этого примера квантификатор {n,} используется для поиска строки, состоящей по крайней мере из трех символов, после которых стоит точка.The regular expression in that example uses the {n,} quantifier to match a string that has at least three characters followed by a period.

Совпадение от n до m раз (ленивое совпадение): {n,m}?Match Between n and m Times (Lazy Match): {n,m}?

Квантификатор {n,m}? сопоставляет предыдущий элемент от n до m раз (где n и m — целые числа), но как можно меньшее количество раз.The {n,m}? quantifier matches the preceding element between n and m times, where n and m are integers, but as few times as possible. Это ленивый квантификатор, являющийся аналогом жадного квантификатора {n,m}.It is the lazy counterpart of the greedy quantifier {n,m}.

В следующем примере регулярное выражение \b[A-Z](\w*?\s*?){1,10}[.!?] сопоставляет фразы, содержащие от одного до десяти слов.In the following example, the regular expression \b[A-Z](\w*?\s*?){1,10}[.!?] matches sentences that contain between one and ten words. Ему соответствуют все предложения в исходной строке кроме одного, длина которого составляет 18 слов.It matches all the sentences in the input string except for one sentence that contains 18 words.

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("'{0}' found at position {1}.", match.Value, 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.

Шаблон регулярного выражения определяется, как показано в следующей таблице.The regular expression pattern is defined as shown in the following table.

ШаблонPattern ОписаниеDescription
\b Начало на границе слова.Start at a word boundary.
[A-Z] Совпадение с любым символом верхнего регистра от А до Z.Match an uppercase character from A to Z.
(\w*?\s*?) Совпадение с нулем или несколькими словообразующими символами, за которыми следует один или несколько пробелов, но как можно меньшее количество раз.Match zero or more word characters, followed by one or more white-space characters, but as few times as possible. Это первая захватываемая группа.This is the first capture group.
{1,10} Совпадение с предыдущим шаблоном от 1 до 10 раз.Match the previous pattern between 1 and 10 times.
[.!?] Совпадение с любым из знаков препинания ".", "!" или "?".Match any one of the punctuation characters ".", "!", or "?".

Жадные и ленивые квантификаторыGreedy and Lazy Quantifiers

У некоторых квантификаторов есть две версии.A number of the quantifiers have two versions:

  • Жадная версия.A greedy version.

    Жадный квантификатор пытается найти максимально возможное число соответствий элемента.A greedy quantifier tries to match an element as many times as possible.

  • Нежадная (ленивая) версия.A non-greedy (or lazy) version.

    При использовании нежадных идентификаторов предпринимается попытка найти минимально возможное число соответствий элемента.A non-greedy quantifier tries to match an element as few times as possible. Чтобы превратить любой жадный квантификатор в ленивый, добавьте к нему ?.You can turn a greedy quantifier into a lazy quantifier by simply adding a ?.

Представьте простое регулярное выражение, позволяющее находить последние четыре цифры в числовой строке, например в номере кредитной карты.Consider a simple regular expression that is intended to extract the last four digits from a string of numbers such as a credit card number. Версия регулярного выражения с жадным квантификатором * будет выглядеть так: \b.*([0-9]{4})\b.The version of the regular expression that uses the * greedy quantifier is \b.*([0-9]{4})\b. Однако если строка содержит два числа, то с помощью такого регулярного выражения будут найдены только последние четыре цифры второго числа, как показано в следующем примере.However, if a string contains two numbers, this regular expression matches the last four digits of the second number only, as the following example shows.

string greedyPattern = @"\b.*([0-9]{4})\b";
string input1 = "1112223333 3992991999";
foreach (Match match in Regex.Matches(input1, greedyPattern))
   Console.WriteLine("Account ending in ******{0}.", 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.

Регулярное выражение не совпадает с первым числом, так как квантификатор * ищет максимально возможное число совпадений во всей строке, и здесь он находит его в конце строки.The regular expression fails to match the first number because the * quantifier tries to match the previous element as many times as possible in the entire string, and so it finds its match at the end of the string.

Это не то, что нам нужно.This is not the desired behavior. Вместо этого вы можете применить ленивый квантификатор *?, чтобы получить цифры из обоих чисел, как показано в следующем примере.Instead, you can use the *?lazy quantifier to extract digits from both numbers, as the following example shows.

string lazyPattern = @"\b.*?([0-9]{4})\b";
string input2 = "1112223333 3992991999";
foreach (Match match in Regex.Matches(input2, lazyPattern))
   Console.WriteLine("Account ending in ******{0}.", 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.

В большинстве случаев регулярные выражения с жадными и ленивыми квантификаторами возвращают одни и те же результаты.In most cases, regular expressions with greedy and lazy quantifiers return the same matches. Как правило, они возвращают разные значения, если применяется подстановочный метасимвол (.), который соответствует любому символу.They most commonly return different results when they are used with the wildcard (.) metacharacter, which matches any character.

Квантификаторы и пустые соответствияQuantifiers and Empty Matches

Квантификаторы *, + и {n,m} и их ленивые аналоги никогда не повторяются после пустого соответствия, если найдено минимальное количество совпадений.The quantifiers *, +, and {n,m} and their lazy counterparts never repeat after an empty match when the minimum number of captures has been found. Это правило препятствует вхождению квантификаторов в бесконечные циклы при пустых соответствиях частей выражений, если максимальное количество возможных фиксаций группы бесконечно или приближено к бесконечному.This rule prevents quantifiers from entering infinite loops on empty subexpression matches when the maximum number of possible group captures is infinite or near infinite.

Например, ниже в коде показан результат вызова метода Regex.Match с шаблоном регулярного выражения (a?)*, который соответствует нулю или одному символу "a" ноль или несколько раз.For example, the following code shows the result of a call to the Regex.Match method with the regular expression pattern (a?)*, which matches zero or one "a" character zero or more times. Обратите внимание, что отдельная захватываемая группа записывает каждое вхождение "a" и String.Empty, но второго пустого совпадения нет, потому что квантификатор прекращает поиск после первого пустого совпадения.Note that the single capturing group captures each "a" as well as String.Empty, but that there is no second empty match, because the first empty match causes the quantifier to stop repeating.

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: '{0}' at index {1}",
                        match.Value, match.Index);
      if (match.Groups.Count > 1) {
         GroupCollection groups = match.Groups;
         for (int grpCtr = 1; grpCtr <= groups.Count - 1; grpCtr++) {
            Console.WriteLine("   Group {0}: '{1}' at index {2}",
                              grpCtr,
                              groups[grpCtr].Value,
                              groups[grpCtr].Index);
            int captureCtr = 0;
            foreach (Capture capture in groups[grpCtr].Captures) {
               captureCtr++;
               Console.WriteLine("      Capture {0}: '{1}' at index {2}",
                                 captureCtr, capture.Value, 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}.To see the practical difference between a capturing group that defines a minimum and a maximum number of captures and one that defines a fixed number of captures, consider the regular expression patterns (a\1|(?(1)\1)){0,2} and (a\1|(?(1)\1)){2}. Оба регулярных выражения состоят из одной захватываемой группы, которая определяется, как показано в следующей таблице.Both regular expressions consist of a single capturing group, which is defined as shown in the following table.

ШаблонPattern ОписаниеDescription
(a\1 Сопоставление "a" вместе со значением первой захваченной группы...Either match "a" along with the value of the first captured group …
|(?(1) или проверка того, была ли определена первая захваченная группа.or test whether the first captured group has been defined. (Обратите внимание, что конструкция (?(1) не определяет захватываемую группу.)(Note that the (?(1) construct does not define a capturing group.)
\1)) Если первая захваченная группа существует, следует сопоставить ее значение.If the first captured group exists, match its value. Если такая группа отсутствует, для нее сопоставляется значение String.Empty.If the group does not exist, the group will match String.Empty.

Первое регулярное выражение пытается сопоставить этот шаблон от нуля до двух раз. Второй — ровно два раза.The first regular expression tries to match this pattern between zero and two times; the second, exactly two times. Так как первый шаблон достигает своего минимального количества записей при первой записи значения String.Empty, он не повторяет попытку сопоставить a\1. Квантификатор {0,2} допускает только пустые соответствия в последней итерации.Because the first pattern reaches its minimum number of captures with its first capture of String.Empty, it never repeats to try to match a\1; the {0,2} quantifier allows only empty matches in the last iteration. Напротив, второе регулярное выражение соответствует "а", потому что оно вычисляет a\1 второй раз. Минимальное число итераций (2) предписывает обработчику выполнять повтор после пустого соответствия.In contrast, the second regular expression does match "a" because it evaluates a\1 a second time; the minimum number of iterations, 2, forces the engine to repeat after an empty match.

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

См. такжеSee also