Кванторы

Обновлен: Июль 2008

Квантификаторы определяют количество вхождений предшествующего им элемента (знака, группы или класса знаков), которое должно присутствовать во входных данных, чтобы было зафиксировано совпадение.

Квантификаторы в регулярных выражениях .NET Framework

В следующей таблице перечислены квантификаторы, поддерживаемые регулярными выражениями .NET Framework. Количества n и m являются целочисленными константами. Описание различий между "жадными" и "ленивыми" квантификаторами см. в разделе "Жадные и ленивые квантификаторы" после таблицы.

Квантификатор

Описание

*

Предыдущий элемент повторяется ноль или более раз. Эквивалентен выражению {0,}. * — жадный квантификатор, нежадным эквивалентом которого является квантификатор *?.

Например, с помощью регулярного выражения \b91*9*\b можно обнаружить знак 9, стоящий после границы слова. После знака 9 может находиться одно или более вхождений знака 1, после которого, в свою очередь, могут находиться одно или более вхождений знака 9. В следующем примере показано, как использовать это регулярное выражение. Пять из девяти чисел в исходной строке соответствуют заданному шаблону, четыре числа (95, 929, 9129 и 9919) ему не соответствуют.

+

Предыдущий элемент повторяется один или более раз. Этот параметр аналогичен параметру {1,}. + — жадный квантификатор, нежадным эквивалентом которого является квантификатор +?.

Например, с помощью регулярного выражения \ba(n)+\w*?\b осуществляется поиск целых слов, которые начинаются с буквы a, за которой следует одна или несколько букв n. В следующем примере показано, как использовать это регулярное выражение. Регулярное выражение соответствует словам an, annual, announcement и antique и не соответствует словам autumn и all.

?

Предыдущий элемент повторяется ноль или один раз. Этот параметр аналогичен параметру {0,1}. ? — жадный квантификатор, нежадным эквивалентом которого является квантификатор ??.

Например, с помощью регулярного выражения \ban?\b осуществляется поиск целых слов, которые начинаются с буквы a, за которой следует одна или ни одной букв n. Иными словами, предпринимается попытка найти слова a и an. В следующем примере показано, как использовать это регулярное выражение.

{n}

Предыдущий элемент повторяется ровно n раз. {n} — жадный квантификатор, нежадным эквивалентом которого является квантификатор {n}?.

Например, с помощью регулярного выражения \b\d+\,\d{3}\b осуществляется поиск границы слова, за которой следует один или более десятичных знаков, еще три десятичных знака и граница слова. В следующем примере показано, как использовать это регулярное выражение.

{n,}

Предыдущий элемент повторяется по крайней мере n раз. {n,} — жадный квантификатор, нежадным эквивалентом которого является квантификатор {n}?.

Например, с помощью регулярного выражения \b\d{2,}\b\D+ осуществляется поиск границы слова, за которой следует по крайней мере два десятичных знака, граница слова и знак, не являющийся числом. В следующем примере показано, как использовать это регулярное выражение. Регулярное выражение не соответствует фразе 7 days, потому что фраза содержит всего один десятичный знак, но соответствует фразам 10 weeks и 300 years.

{n,m}

Предыдущий элемент повторяется по крайней мере n раз, но не более m раз. {n,m} — жадный квантификатор, нежадным эквивалентом которого является квантификатор {n,m}?.

Например, с помощью регулярного выражения (00\s){2,4} осуществляется поиск от двух до четырех вхождений двух нулей, за которыми следует пробел. В следующем примере показано, как использовать это регулярное выражение. Обратите внимание, что в конце входной строки имеются пять вхождений этого фрагмента при максимуме в четыре вхождения. Однако начало этой части строки (до пробела и пятой пары нулей) соответствует регулярному выражению.

*?

Предыдущий элемент повторяется ноль или более раз, но как можно меньшее число раз. Это ленивый квантификатор, дополняющий жадный квантификатор *.

Например, с помощью регулярного выражения \b\w*?oo\w*?\b осуществляется поиск всех слов, содержащих строку oo. В следующем примере показано, как использовать это регулярное выражение.

+?

Предыдущий элемент повторяется один или более раз, но как можно меньшее число раз. Это ленивый квантификатор, дополняющий жадный квантификатор +.

Например, с помощью регулярного выражения \b\w+?\b осуществляется поиск одного или нескольких знаков, разделенных границами слов. В следующем примере показано, как использовать это регулярное выражение.

??

Предыдущий элемент повторяется ноль или один раз, но как можно меньшее число раз. Это ленивый квантификатор, дополняющий жадный квантификатор ?.

Например, с помощью регулярного выражения ^(\s)*(System.)??Console.Write(Line)??\(?? осуществляется поиск строки Console.Write или Console.WriteLine. Строка может включать System. перед Console, а также открывающую скобку в конце. Искомый текст должен находиться в начале строки, хотя перед ним может стоять пробел. В следующем примере показано, как использовать это регулярное выражение.

{n}?

Предыдущий элемент повторяется ровно n раз. Это ленивый квантификатор, дополняющий жадный квантификатор {n}+.

Например, с помощью регулярного выражения \b(\w{3,}?\.){2}?\w{3,}?\b осуществляется поиск ровно двух наборов знаков с точкой в конце на границе слова. После этих наборов и точки должен располагаться еще один набор знаков и граница слова. Такое регулярное выражение позволяет выявлять адреса веб-узлов. В следующем примере показано, как использовать это регулярное выражение. Обратите внимание, что оно соответствует строкам www.microsoft.com и mdsn.microsoft.com, но не соответствует строкам mywebsite и mycompany.com.

{n,}?

Предыдущий элемент повторяется по крайней мере n раз, но как можно меньшее число раз. Это ленивый квантификатор, дополняющий жадный квантификатор {n,}.

В качестве демонстрации его использования см. пример для квантификатора {n}?. В регулярном выражении из этого примера квантификатор {n,} используется для поиска строки, состоящей по крайней мере из трех знаков, после которых стоит точка.

{n,m}?

Предыдущий элемент повторяется не меньше n и не больше m раз, но как можно меньшее число раз. Это ленивый квантификатор, дополняющий жадный квантификатор {n,m}.

Например, с помощью регулярного выражения \b[A-Z](\w*?\s*?){1,10}[.!?] осуществляется поиск предложений, содержащих от одного до десяти слов. Соответствующие этому регулярному выражению фрагменты начинаются с границы слова, за которой следует прописная буква и от одного до десяти слов с необязательным пробелом. Фрагмент должен заканчиваться точкой, восклицательным или вопросительным знаком. В следующем примере показано, как использовать это регулярное выражение. Ему соответствуют все приложения исходной строки, кроме одного предложения, длина которого составляет 18 слов.

Жадные и ленивые квантификаторы

У некоторых квантификаторов есть две версии.

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

    При использовании жадных квантификаторов предпринимается попытка найти максимально возможное число элементов, к которым относятся эти квантификаторы.

  • Нежадная (ленивая) версия.

    При использовании нежадных квантификаторов предпринимается попытка найти минимально возможное число элементов, к которым относятся эти квантификаторы.

Чтобы понять различие, представьте себе очень простое регулярное выражение, позволяющее находить последние четыре цифры в числовой строке, например в номере кредитной карты. Версия этого выражения с жадным квантификатором * будет иметь вид \b.*([0-9]{4})\b. Однако если исходная строка содержит два числа, то с помощью такого регулярного выражения будут найдены только последние четыре знака второго числа, как показано в следующем примере.

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

В большинстве случаев регулярные выражения с жадными и ленивыми квантификаторами возвращают одни и те же результаты. Результаты обычно различаются, если в регулярных выражениях используется метазнак точка ( . ), который соответствует любому знаку.

См. также

Другие ресурсы

Элементы языка регулярных выражений

Журнал изменений

Дата

Журнал изменений

Причина

Июль 2008

Проведена значительная переработка.

Исправление ошибки содержимого.