Квантификаторы определяют количество вхождений предшествующего им элемента (знака, группы или класса знаков), которое должно присутствовать во входных данных, чтобы было зафиксировано совпадение.
Квантификаторы в регулярных выражениях .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}?.
Например, с помощью регулярного выражения \b\d+\,\d{3}\b осуществляется поиск границы слова, за которой следует один или более десятичных знаков, еще три десятичных знака и граница слова. В следующем примере показано, как использовать это регулярное выражение.
Предыдущий элемент повторяется по крайней мере n раз. {n,} — жадный квантификатор, нежадным эквивалентом которого является квантификатор {n}?.
Например, с помощью регулярного выражения \b\d{2,}\b\D+ осуществляется поиск границы слова, за которой следует по крайней мере два десятичных знака, граница слова и знак, не являющийся числом. В следующем примере показано, как использовать это регулярное выражение. Регулярное выражение не соответствует фразе 7 days, потому что фраза содержит всего один десятичный знак, но соответствует фразам 10 weeks и 300 years.
Предыдущий элемент повторяется по крайней мере 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}+.
Например, с помощью регулярного выражения \b(\w{3,}?\.){2}?\w{3,}?\b осуществляется поиск ровно двух наборов знаков с точкой в конце на границе слова. После этих наборов и точки должен располагаться еще один набор знаков и граница слова. Такое регулярное выражение позволяет выявлять адреса веб-узлов. В следующем примере показано, как использовать это регулярное выражение. Обратите внимание, что оно соответствует строкам www.microsoft.com и mdsn.microsoft.com, но не соответствует строкам mywebsite и mycompany.com.
Предыдущий элемент повторяется по крайней мере 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.
В большинстве случаев регулярные выражения с жадными и ленивыми квантификаторами возвращают одни и те же результаты. Результаты обычно различаются, если в регулярных выражениях используется метазнак точка ( . ), который соответствует любому знаку.