Spec-Zone .ru
спецификации, руководства, описания, API
След: Существенные Классы
Урок: Регулярные выражения
Кванторы
Домашняя страница > Существенные Классы > Регулярные выражения

Кванторы

Кванторы позволяют Вам определять число возникновений, чтобы соответствовать против. Для удобства три раздела спецификации API Образца, описывающей жадные, неохотные, и притяжательные кванторы, представляются ниже. На первый взгляд может казаться что кванторы X?, X?? и X?+ сделайте точно ту же самую вещь, так как они все обещают соответствовать"X, однажды или нисколько". Есть тонкие различия в реализации, которые будут объяснены около конца этого раздела.

Жадный Отказывающийся Притяжательный Значение
X? X?? X?+ X, однажды или нисколько
X* X*? X*+ X, нуль или больше раз
X+ X+? X++ X, один или более раз
X{n} X{n}? X{n}+ X, точно n времена
X{n,} X{n,}? X{n,}+ X, по крайней мере, n времена
X{n,m} X{n,m}? X{n,m}+ X, по крайней мере, n но не больше чем m времена

Давайте запустим наш взгляд на жадные кванторы, создавая три различных регулярных выражения: буква "a" следовала также ?, *, или +. Давайте видеть то, что происходит, когда эти выражения тестируются против пустой строки ввода "":

 
Enter your regex: a?
Enter input string to search: 
I found the text "" starting at index 0 and ending at index 0.

Enter your regex: a*
Enter input string to search: 
I found the text "" starting at index 0 and ending at index 0.

Enter your regex: a+
Enter input string to search: 
No match found.

Соответствия нулевые длиной

В вышеупомянутом примере соответствие успешно в первых двух случаях потому что выражения a? и a* оба учитывают нулевые возникновения буквы a. Вы также заметите, что запуск и заканчивается, индексы являются оба нулем, который непохож на любой из примеров, которые мы до сих пор видели. Пустая строка ввода "" не имеет никакой длины, таким образом, тест просто соответствует, ничто в не индексирует 0. Соответствия этого вида известны как соответствия нулевые длиной. Соответствие нулевое длиной может произойти в нескольких случаях: в пустой строке ввода, в начале строки ввода, после последнего знака строки ввода, или промежуточный любые два символа строки ввода. Соответствия нулевые длиной легко идентифицируемы, потому что они всегда запускают и заканчиваются в том же самом, индексируют позицию.

Давайте исследовать соответствия нулевые длиной еще с несколькими примерами. Измените строку ввода на одну букву "a", и Вы заметите что-то интересное:

 
Enter your regex: a?
Enter input string to search: a
I found the text "a" starting at index 0 and ending at index 1.
I found the text "" starting at index 1 and ending at index 1.

Enter your regex: a*
Enter input string to search: a
I found the text "a" starting at index 0 and ending at index 1.
I found the text "" starting at index 1 and ending at index 1.

Enter your regex: a+
Enter input string to search: a
I found the text "a" starting at index 0 and ending at index 1.

Все три квантора, найденные буквой "a", но первыми двумя также, нашли, что соответствие нулевое длиной в индексирует 1; то есть, после последнего знака строки ввода. Помните, matcher видит символ "a", поскольку находящийся в ячейке между индексируют 0 и индексируют 1, и наши тестовые циклы ремня безопасности, пока это больше не может найти соответствие. В зависимости от используемого квантора присутствие "ничего" при индексировании после того, как последний знак не может или, возможно, не инициировал соответствие.

Теперь измените строку ввода на букву "a" пять раз подряд, и Вы получите следующее:

 
Enter your regex: a?
Enter input string to search: aaaaa
I found the text "a" starting at index 0 and ending at index 1.
I found the text "a" starting at index 1 and ending at index 2.
I found the text "a" starting at index 2 and ending at index 3.
I found the text "a" starting at index 3 and ending at index 4.
I found the text "a" starting at index 4 and ending at index 5.
I found the text "" starting at index 5 and ending at index 5.

Enter your regex: a*
Enter input string to search: aaaaa
I found the text "aaaaa" starting at index 0 and ending at index 5.
I found the text "" starting at index 5 and ending at index 5.

Enter your regex: a+
Enter input string to search: aaaaa
I found the text "aaaaa" starting at index 0 and ending at index 5.

Выражение a? находит отдельное соответствие для каждого символа, так как он соответствует, когда "a" кажется нуль или времена. Выражение a* находит два отдельных соответствия: вся буква "a" 's в первом соответствии, тогда соответствие нулевое длиной после последнего знака в индексируют 5. И наконец, a+ соответствия все возникновения буквы "a", игнорируя присутствие "ничего" в последнем не индексируют.

В этой точке Вы могли бы задаваться вопросом, чем будут состоять в том результаты, если первые два квантора встретятся с буквой кроме "a". Например, что происходит, если это встречается с буквой "b", как в "ababaaaab"?

Давайте узнаем:

 
Enter your regex: a?
Enter input string to search: ababaaaab
I found the text "a" starting at index 0 and ending at index 1.
I found the text "" starting at index 1 and ending at index 1.
I found the text "a" starting at index 2 and ending at index 3.
I found the text "" starting at index 3 and ending at index 3.
I found the text "a" starting at index 4 and ending at index 5.
I found the text "a" starting at index 5 and ending at index 6.
I found the text "a" starting at index 6 and ending at index 7.
I found the text "a" starting at index 7 and ending at index 8.
I found the text "" starting at index 8 and ending at index 8.
I found the text "" starting at index 9 and ending at index 9.

Enter your regex: a*
Enter input string to search: ababaaaab
I found the text "a" starting at index 0 and ending at index 1.
I found the text "" starting at index 1 and ending at index 1.
I found the text "a" starting at index 2 and ending at index 3.
I found the text "" starting at index 3 and ending at index 3.
I found the text "aaaa" starting at index 4 and ending at index 8.
I found the text "" starting at index 8 and ending at index 8.
I found the text "" starting at index 9 and ending at index 9.

Enter your regex: a+
Enter input string to search: ababaaaab
I found the text "a" starting at index 0 and ending at index 1.
I found the text "a" starting at index 2 and ending at index 3.
I found the text "aaaa" starting at index 4 and ending at index 8.

Даже при том, что буква "b" появляется в ячейках 1, 3, и 8, вывод сообщает о соответствии нулевом длиной в тех расположениях. Регулярное выражение a? определенно не ищет букву "b"; это просто ищет присутствие (или нехватка этого) буквы "a". Если квантор учитывает соответствие нулевых времен "a", что-либо в строке ввода это не "a", обнаружится как соответствие нулевое длиной. Остающийся a's является соответствующим согласно правилам, обсужденным в предыдущих примерах.

Чтобы соответствовать образец точно n число раз, просто определите число в ряде фигурных скобок:

 
Enter your regex: a{3}
Enter input string to search: aa
No match found.

Enter your regex: a{3}
Enter input string to search: aaa
I found the text "aaa" starting at index 0 and ending at index 3.

Enter your regex: a{3}
Enter input string to search: aaaa
I found the text "aaa" starting at index 0 and ending at index 3.

Здесь, регулярное выражение a{3} ищет три возникновения буквы "a" подряд. Первый тест перестал работать, потому что у строки ввода нет достаточного количества a's, чтобы соответствовать против. Второй тест содержит точно 3 a's в строке ввода, которая инициировала соответствие. Третий тест также инициировал соответствие, потому что есть точно 3 a's в начале строки ввода. Что-либо после этого не важно первому соответствию. Если бы образец должен появиться снова после той точки он инициировал бы последующие соответствия:

 
Enter your regex: a{3}
Enter input string to search: aaaaaaaaa
I found the text "aaa" starting at index 0 and ending at index 3.
I found the text "aaa" starting at index 3 and ending at index 6.
I found the text "aaa" starting at index 6 and ending at index 9.

Чтобы потребовать, чтобы образец казался, по крайней мере, n времена, добавьте запятую после числа:

 
Enter your regex: a{3,}
Enter input string to search: aaaaaaaaa
I found the text "aaaaaaaaa" starting at index 0 and ending at index 9.

С той же самой строкой ввода этот тест находит только одно соответствие, потому что 9 a's подряд удовлетворяют потребность в "по крайней мере" 3 a's.

Наконец, чтобы определить верхний предел числа occurances, добавьте второе число в фигурных скобках:

 
Enter your regex: a{3,6} // find at least 3 (but no more than 6) a's in a row
Enter input string to search: aaaaaaaaa
I found the text "aaaaaa" starting at index 0 and ending at index 6.
I found the text "aaa" starting at index 6 and ending at index 9.

Здесь первое соответствие вынуждается остановиться в верхнем пределе 6 символов. Второе соответствие включает то, что переносится, который, оказывается, три a's — mimimum число символов, учтенных это соответствие. Если бы строка ввода была одним символом короче, не было бы второго соответствия, так как только два a's остались бы.

Группы фиксации и Классы символов с Кванторами

До сих пор мы только протестировали кванторы на строках ввода, содержащих один символ. Фактически, кванторы могут только присоединить к одному символу за один раз, таким образом, регулярное выражение "abc +" означало бы "a, сопровождаемый b, сопровождаемым c один или более раз". Это не означало бы "abc" один или более раз. Однако, кванторы могут также присоединить к Классам символов и Группам фиксации, такой как [abc]+ (a или b или c, один или более раз) или (abc)+ (группа "abc", один или более раз).

Давайте иллюстрировать, определяя группу (dog), три раза подряд.

 
Enter your regex: (dog){3}
Enter input string to search: dogdogdogdogdogdog
I found the text "dogdogdog" starting at index 0 and ending at index 9.
I found the text "dogdogdog" starting at index 9 and ending at index 18.

Enter your regex: dog{3}
Enter input string to search: dogdogdogdogdogdog
No match found.

Здесь первый пример находит три соответствия, так как квантор применяется ко всей группе фиксации. Раскройте скобки, однако, и сбои соответствия потому что квантор {3} теперь применяется только к букве "g".

Точно так же мы можем применить квантор ко всему символьному class:

Enter your regex: [abc]{3}
Enter input string to search: abccabaaaccbbbc
I found the text "abc" starting at index 0 and ending at index 3.
I found the text "cab" starting at index 3 and ending at index 6.
I found the text "aaa" starting at index 6 and ending at index 9.
I found the text "ccb" starting at index 9 and ending at index 12.
I found the text "bbc" starting at index 12 and ending at index 15.

Enter your regex: abc{3}
Enter input string to search: abccabaaaccbbbc
No match found.

Здесь квантор {3} применяется ко всему символьному class в первом примере, но только к букве "c" во втором.

Различия Среди Жадных, Неохотных, и Притяжательных Кванторов

Среди жадных, неохотных, и притяжательных кванторов есть тонкие различия.

Жадные кванторы считают "жадными", потому что они вынуждают matcher читать в, или поесть, вся строка ввода до попытки первого соответствия. Если первая попытка соответствия (вся строка ввода) сбои, matcher замедляет строку ввода одним символом и попробовал еще раз, повторяя процесс, пока соответствие не находится или нет больше символов, оставленных отступать от. В зависимости от квантора, используемого в выражении, последней вещью, против которой это попытается соответствовать, являются 1 или 0 символов.

Неохотные кванторы, однако, проявляют противоположный подход: Они запускают в начале строки ввода, тогда неохотно едят один символ, за один раз ища соответствие. Последней вещью, которую они пробуют, является вся строка ввода.

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

Чтобы иллюстрировать, рассмотрите строку ввода xfooxxxxxxfoo.

 
Enter your regex: .*foo  // greedy quantifier
Enter input string to search: xfooxxxxxxfoo
I found the text "xfooxxxxxxfoo" starting at index 0 and ending at index 13.

Enter your regex: .*?foo  // reluctant quantifier
Enter input string to search: xfooxxxxxxfoo
I found the text "xfoo" starting at index 0 and ending at index 4.
I found the text "xxxxxxfoo" starting at index 4 and ending at index 13.

Enter your regex: .*+foo // possessive quantifier
Enter input string to search: xfooxxxxxxfoo
No match found.

Первый пример использует жадный квантор .* счесть "что-либо", нуль или больше раз, сопровождаемыми буквами "f" "o" "o". Поскольку квантор является жадным, .* часть выражения сначала ест всю строку ввода. В этой точке полное выражение не может успешно выполниться, потому что последние три буквы ("f" "o" "o") были уже использованы. Таким образом, matcher медленно замедляет одну букву за один раз, пока самое правое возникновение "foo" не было извергнуто, в которой точке соответствие успешно выполняется и концы поиска.

Второй пример, однако, отказывается, таким образом, он запускается первым потреблением "ничего". Поскольку "foo" не появляется в начале строки, он вынуждается глотать первую букву ("x"), который инициировал первое соответствие в 0 и 4. Наш тестовый ремень безопасности продолжает процесс, пока строка ввода не исчерпывается. Это находит другое соответствие в 4 и 13.

Третий пример не в состоянии найти соответствие, потому что квантор является притяжательным. В этом случае вся строка ввода используется .*+, переносить ничто, чтобы удовлетворить "foo" в конце выражения. Используйте притяжательный квантор для ситуаций, где Вы хотите захватить все что-то без когда-либо отступления; это выиграет у эквивалентного жадного квантора в случаях, где соответствие не было сразу найдено.


Проблемы с примерами? Попытайтесь Компилировать и Выполнить Примеры: FAQ.
Жалобы? Поздравление? Предложения? Дайте нам свою обратную связь.

Предыдущая страница: Предопределенные Классы символов
Следующая страница: Группы фиксации