7.8 KiB
Квантификаторы +, *, ? и {n}
Рассмотрим ту же задачу, что и ранее -- взять телефон вида +7(903)-123-45-67
и найти все числа в нём. Но теперь нас интересуют не цифры по отдельности, а именно числа, то есть результат вида 7, 903, 123, 45, 67
.
Для поиска цифр по отдельности нам было достаточно класса \d
. Но здесь нужно искать числа -- последовательности из 1 или более цифр.
Количество {n}
Количество повторений символа можно указать с помощью числа в фигурных скобках: {n}
.
Такое указание называют квантификатором (от англ. quantifier).
У него есть несколько подформ записи:
- Точное количество: `{5}`
- Регэксп
\d{5}
обозначает ровно 5 цифр, в точности как\d\d\d\d\d
.Следующий пример находит пятизначное число.
//+ run alert( "Мне 12345 лет".match (/\d{5}/) ); // "12345"
- Количество от-до: `{3,5}`
- Для того, чтобы найти, например, числа размером от трёх до пяти знаков, нужно указать границы в фигурных скобках:
\d{3,5}
//+ run alert( "Мне не 12, а 1234 года".match( /\d{3,5}/ ) ); // "1234"
Последнее значение можно и не указывать. Тогда выражение
\d{3,}
найдет числа, длиной от трех цифр://+ run alert( "Мне не 12, а 345678 лет".match( /\d{3,5}/ ) ); // "345678"
В случае с телефоном нам нужны числа -- одна или более цифр подряд. Этой задаче соответствует регулярное выражение \d{1,}
:
//+ run
var str = "+7(903)-123-45-67";
alert( str.match( /\d{1,}/g ) ); // 7,903,123,45,67
Короткие обозначения
Для самые часто востребованных квантификаторов есть специальные короткие обозначения.
- `+`
- Означает "один или более", то же что `{1,}`.
Например,
\d+
находит числа -- последовательности из 1 или более цифр://+ run var str = "+7(903)-123-45-67"; alert( str.match( /\d+/g ) ); // 7,903,123,45,67
- `?`
- Означает "ноль или один", то же что и `{0,1}`. По сути, делает символ необязательным.
Например, регэксп
ou?r
найдётo
, после которого, возможно, следуетu
, а затемr
.Этот регэксп найдёт
or
в словеcolor
иour
вcolour
://+ run var str = "Можно писать color или colour (британский вариант)"; alert( str.match( /colou?r/g ) ); // color, colour
- `*`
- Означает "ноль или более", то же что `{0,}`. То есть, символ может повторяться много раз или вообще отсутствовать.
Пример ниже находит цифру, после которой идёт один или более нулей:
//+ run alert( "100 10 1".match( /\d0*/g ) ); // 100, 10, 1
Сравните это с
'+'
(один или более)://+ run alert( "100 10 1".match( /\d0+/g ) ); // 100, 10
Ещё примеры
Эти квантификаторы принадлежат к числу самых важных "строительных блоков" для сложных регулярных выражений, поэтому мы рассмотрим ещё примеры.
- Регэксп "десятичная дробь" (число с точкой внутри):
\d+\.\d+
-
В действии:
//+ run alert( "0 1 12.345 7890".match( /\d+\.\d+/g ) ); // 123.45
- Регэксп "открывающий HTML-тег без атрибутов", такой как `` или `
`:
/<[a-z]+>/i
- Пример:
//+ run alert( "<BODY> ... </BODY>".match ( /<[a-z]+>/gi ) ); // <BODY>
Это регулярное выражение ищет символ
'<'
, за которым идут одна или более букв английского алфавита, и затем'>'
. - Регэксп "открывающий HTML-тег без атрибутов" (лучше):
/<[a-z][a-z0-9]*>/i
-
Здесь регулярное выражение расширено: в соответствие со стандартом, HTML-тег может иметь символ на любой позиции, кроме первой, например `
`.
//+ run alert( "<h1>Привет!</h1>".match( /<[a-z][a-z0-9]*>/gi ) ); // <h1>
- Регэксп "открывающий или закрывающий HTML-тег без атрибутов":
/<\/?[a-z][a-z0-9]*>/i
- В предыдущий паттерн добавили необязательный слэш
/?
перед тегом. Его понадобилось заэкранировать, чтобы JavaScript не принял его за конец шаблона.//+ run alert( "<h1>Привет!</h1>".match( /<\/?[a-z][a-z0-9]*>/gi ) ); // <h1>, </h1>
[smart header="Точнее -- значит сложнее"] В этих примерах мы видим общее правило, которое повторяется из раза в раз: чем точнее регулярное выражение, тем оно длиннее и сложнее.
Например, для HTML-тегов, скорее всего, подошло бы и более короткое регулярное выражение <\w+>
.
Так как класс \w
означает "любая цифра или английская буква или '_'
, то под такой регэксп подойдут и не теги, например <_>
. Однако он гораздо проще, чем более точный регэксп <[a-z][a-z0-9]*>
.
Подойдёт ли нам <\w+>
или нужно использовать именно <[a-z][a-z0-9]*>
?
В реальной жизни допустимы оба варианта. Ответ на подобные вопросы зависит от того, насколько реально важна точность и насколько сложно потом будет отфильтровать лишние совпадения (если появятся). [/smart]