Regexp.prototype.test()
Содержание:
Статические свойства
Ну и напоследок — еще одна совсем оригинальная особенность регулярных выражений.
Вот — одна интересная функция.
Запустите ее один раз, запомните результат — и запустите еще раз.
function rere() { var re1 = /0/, re2 = new RegExp('0') alert() re1.foo = 1 re2.foo = 1 }
rere()
В зависимости от браузера, результат первого запуска может отличаться от второго. На текущий момент, это так для Firefox, Opera. При этом в Internet Explorer все нормально.
С виду функция создает две локальные переменные и не зависит от каких-то внешних факторов.
Почему же разный результат?
Ответ кроется в стандарте ECMAScript, :
Цитата…
A regular expression literal is an input element that is converted to a RegExp object (section 15.10)
when it is scanned. The object is created before evaluation of the containing program or function begins.
Evaluation of the literal produces a reference to that object; it does not create a new object.
То есть, простыми словами, литеральный регэксп не создается каждый раз при вызове .
Вместо этого браузер возвращает уже существующий объект, со всеми свойствами, оставшимися от предыдущего запуска.
В отличие от этого, всегда создает новый объект, поэтому и ведет себя в примере по-другому.
Методы Javascript для работы с регулярными выражениями
В Javascript Существует 6 методов для работы с регулярными выражениями. Чаще всего мы будем использовать только половину из них.
Метод exec()
Метод RegExp, который выполняет поиск совпадения в строке. Он возвращает массив данных. Например:
var str = 'Some fruit: Banana - 5 pieces. For 15 monkeys.'; var re = /(\w+) - (\d) pieces/ig; var result = re.exec(str); window.console.log(result); // result = // Так же мы можем посмотреть позицию совпадения - result.index
В результате мы получим массив, первым элементом которого будет вся совпавшая по паттерну строка, а дальше содержимое скобочных групп. Если совпадений с паттерном нету, то .
Метод test()
Метод RegExp, который проверяет совпадение в строке, возвращает либо true, либо false. Очень удобен, когда нам необходимо проверить наличие или отсутствие паттерна в тексте. Например:
var str = 'Balance: 145335 satoshi'; var re = /Balance:/ig; var result = re.test(str); window.console.log(result); // true
В данном примере, есть совпадение с паттерном, поэтому получаем true.
Метод search()
Метод String, который тестирует на совпадение в строке. Он возвращет индекс совпадения, или -1 если совпадений не будет найдено. Очень похож на метод indexOf() для работы со строками. Минус этого метода — он ищет только первое совпадение. Для поиска всех совпадений используйте метод match().
var str = "Умея автоматизировать процессы, можно зарабатывать миллионы"; window.console.log(str.search(/можно/igm)); // 60 window.console.log(str.search(/атата/igm)); // -1
Метод match()
Метод String, который выполняет поиск совпадения в строке. Он возвращет массив данных либо null если совпадения отсутствуют.
// Без использования скобочных групп var str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; var regexp = //gi; var matches_array = str.match(regexp); window.console.log(matches_array); // // С использованием скобочных групп без флага g var str = 'Fruits quantity: Apple - 5, Banana - 7, Orange - 12. I like fruits.'; var found = str.match(/(\d{1,2})/i); window.console.log(found); // Находит первое совпадение и возвращает объект // { // 0: "5" // 1: "5" // index: 25 // input: "Fruits quantity: Apple -...ge - 12. I like fruits." // } // С использованием скобочных групп с флагом g var found = str.match(/(\d{1,2})/igm); window.console.log(found); //
Если совпадений нету — возвращает null.
Метод replace()
Метод String, который выполняет поиск совпадения в строке, и заменяет совпавшую подстроку другой подстрокой переданной как аргумент в этот метод. Мы уже использовали эту функцию для работы о строками, регулярные выражения привносят новые возможности.
// Обычная замена var str = 'iMacros is awesome, and iMacros is give me profit!'; var newstr = str.replace(/iMacros/gi, 'Javascript'); window.console.log(newstr); // Javascript is awesome, and Javascript is give me profit! // Замена, используя параметры. Меняем слова местами: var re = /(\w+)\s(\w+)/; var str = 'iMacros JS'; var newstr = str.replace(re, '$2, $1'); // в переменных $1 и $2 находятся значения из скобочных групп window.console.log(newstr); // JS iMacros
У метода replace() есть очень важная особенность — он имеет свой каллбэк. То есть, в качестве аргумента мы можем подавать функцию, которая будет обрабатывать каждое найденное совпадение.
Нестандартное применение метода replace():
var str = ` I have some fruits: Orange - 5 pieces Banana - 7 pieces Apple - 15 pieces It's all. `; var arr = []; // Сюда складируем данные о фруктах и их количестве var newString = str.replace(/(\w+) - (\d) pieces/igm, function (match, p1, p2, offset, string) { window.console.log(arguments); arr.push({ name: p1, quantity: p2 }); return match; }); window.console.log(newString); // Текст не изменился, как и было задумано window.console.log(arr); // Мы получили удобный массив объектов, с которым легко и приятно работать
Как вы видите, мы использовали этот метод для обработки каждого совпадения. Мы вытащили из паттерна название фрукта и количество и поместили эти значения в массив объектов, как мы уже делали ранее
Обратите внимание на аргумент функции offset — это будет индекс начала совпадения, этот параметр нам потом пригодится. В нашем случае, мы имеем 2 скобочные группы в паттерне, поэтому у нас в функции 5 аргументов, но их там может быть и больше
Метод split()
Метод String, который использует регулярное выражение или фиксированую строку чтобы разбить строку на массив подстрок.
var str = "08-11-2016"; // Разбиваем строку по разделителю window.console.log(str.split('-')); // // Такой же пример с регэкспом window.console.log(str.split(/-/)); //
Specify Pattern Using RegEx
To specify regular expressions, metacharacters are used. In the above example (), and are metacharacters.
MetaCharacters
Metacharacters are characters that are interpreted in a special way by a RegEx engine. Here’s a list of metacharacters:
[] . ^ $ * + ? {} () \ |
— Square brackets
Square brackets specify a set of characters you wish to match.
Expression | String | Matched? |
---|---|---|
1 match | ||
2 matches | ||
No match | ||
5 matches |
Here, will match if the string you are trying to match contains any of the , or .
You can also specify a range of characters using inside square brackets.
is the same as .
is the same as .
is the same as .
You can complement (invert) the character set by using caret symbol at the start of a square-bracket.
means any character except or or .
means any non-digit character.
— Period
A period matches any single character (except newline ).
Expression | String | Matched? |
---|---|---|
No match | ||
1 match | ||
1 match | ||
2 matches (contains 4 characters) |
— Caret
The caret symbol is used to check if a string starts with a certain character.
Expression | String | Matched? |
---|---|---|
1 match | ||
1 match | ||
No match | ||
1 match | ||
No match (starts with but not followed by ) |
— Dollar
The dollar symbol is used to check if a string ends with a certain character.
Expression | String | Matched? |
---|---|---|
1 match | ||
1 match | ||
No match |
— Star
The star symbol matches zero or more occurrences of the pattern left to it.
Expression | String | Matched? |
---|---|---|
1 match | ||
1 match | ||
1 match | ||
No match ( is not followed by ) | ||
1 match |
— Plus
The plus symbol matches one or more occurrences of the pattern left to it.
Expression | String | Matched? |
---|---|---|
No match (no character) | ||
1 match | ||
1 match | ||
No match ( is not followed by ) | ||
1 match |
— Question Mark
The question mark symbol matches zero or one occurrence of the pattern left to it.
Expression | String | Matched? |
---|---|---|
1 match | ||
1 match | ||
No match (more than one character) | ||
No match ( is not followed by ) | ||
1 match |
— Braces
Consider this code: . This means at least , and at most repetitions of the pattern left to it.
Expression | String | Matched? |
---|---|---|
No match | ||
1 match (at ) | ||
2 matches (at and ) | ||
2 matches (at and ) |
Let’s try one more example. This RegEx matches at least 2 digits but not more than 4 digits.
Expression | String | Matched? |
---|---|---|
1 match (match at ) | ||
3 matches (, , ) | ||
No match |
— Alternation
Vertical bar is used for alternation ( operator).
Expression | String | Matched? |
---|---|---|
No match | ||
1 match (match at ) | ||
3 matches (at ) |
Here, match any string that contains either or
— Group
Parentheses is used to group sub-patterns. For example, match any string that matches either or or followed by
Expression | String | Matched? |
---|---|---|
No match | ||
1 match (match at ) | ||
2 matches (at ) |
— Backslash
Backslash is used to escape various characters including all metacharacters. For example,
match if a string contains followed by . Here, is not interpreted by a RegEx engine in a special way.
If you are unsure if a character has special meaning or not, you can put in front of it. This makes sure the character is not treated in a special way.
Special Sequences
Special sequences make commonly used patterns easier to write. Here’s a list of special sequences:
— Matches if the specified characters are at the start of a string.
Expression | String | Matched? |
---|---|---|
Match | ||
No match |
— Matches if the specified characters are at the beginning or end of a word.
Expression | String | Matched? |
---|---|---|
Match | ||
Match | ||
No match | ||
Match | ||
Match | ||
No match |
— Opposite of . Matches if the specified characters are not at the beginning or end of a word.
Expression | String | Matched? |
---|---|---|
No match | ||
No match | ||
Match | ||
No match | ||
No match | ||
Match |
— Matches any decimal digit. Equivalent to
Expression | String | Matched? |
---|---|---|
3 matches (at ) | ||
No match |
— Matches any non-decimal digit. Equivalent to
Expression | String | Matched? |
---|---|---|
3 matches (at ) | ||
No match |
— Matches where a string contains any whitespace character. Equivalent to .
Expression | String | Matched? |
---|---|---|
1 match | ||
No match |
— Matches where a string contains any non-whitespace character. Equivalent to .
Expression | String | Matched? |
---|---|---|
2 matches (at ) | ||
No match |
— Matches any alphanumeric character (digits and alphabets). Equivalent to . By the way, underscore is also considered an alphanumeric character.
Expression | String | Matched? |
---|---|---|
3 matches (at ) | ||
No match |
— Matches any non-alphanumeric character. Equivalent to
Expression | String | Matched? |
---|---|---|
1 match (at ) | ||
No match |
— Matches if the specified characters are at the end of a string.
Expression | String | Matched? |
---|---|---|
1 match | ||
No match | ||
No match |
Tip: To build and test regular expressions, you can use RegEx tester tools such as regex101. This tool not only helps you in creating regular expressions, but it also helps you learn it.
Now you understand the basics of RegEx, let’s discuss how to use RegEx in your JavaScript code.
Советы и подсказки
Если вы захотите найти символ слеша, нужно экранизировать его с помощью обратного слеша. То же самое верно для других символов, которые имеют особое значение, например, вопросительного знака. Вот JavaScript regexp пример того, как их искать:
var slashSearch = ///; var questionSearch = /?/;
- d – это то же самое, что и : каждая конструкция соответствует цифровому символу.
- w – это то же самое, что : оба выражения соответствуют любому одиночному алфавитно-цифровому символу или подчеркиванию.
Пример: добавляем пробелы в строки, написанные в «верблюжьем» стиле
В этом примере мы очень устали от «верблюжьего» стиля написания и нам нужен способ добавить пробелы между словами. Вот пример:
removeCc('camelCase') // => должен вернуть 'camel Case'
Существует простое решение с использованием регулярного выражения. Во-первых, нам нужно найти все заглавные буквы. Это можно сделать с помощью поиска набора символов и глобального модификатора.
Это соответствует символу «C» в «camelCase»
//g
Теперь, как добавить пробел перед «C»?
Нам нужно использовать захватывающие скобки! Они позволяют найти соответствие и запомнить его, чтобы использовать позже! Используйте захватывающие скобки, чтобы запомнить найденную заглавную букву:
/()/
Получить доступ к захваченному значению позднее можно так:
$1
Выше мы используем $1 для доступа к захваченному значению. Кстати, если бы у нас было два набора захватывающих скобок, мы использовали бы $1 и $2 для ссылки на захваченные значения и аналогично для большего количества захватывающих скобок.
Если вам нужно использовать скобки, но не нужно фиксировать это значение, можно использовать незахватывающие скобки: (?: x). В этом случае находится соответствие x, но оно не запоминается.
Вернемся к текущей задаче. Как мы реализуем захватывающие скобки? С помощью метода JavaScript regexp replace! В качестве второго аргумента мы передаем «$1»
Здесь важно использовать кавычки
function removeCc(str){ return str.replace(/()/g, '$1'); }
Снова посмотрим на код. Мы захватываем прописную букву, а затем заменяем ее той же самой буквой. Внутри кавычек вставим пробел, за которым следует переменная $1. В итоге получаем пробел после каждой заглавной буквы.
function removeCc(str){ return str.replace(/()/g, ' $1'); } removeCc('camelCase') // 'camel Case' removeCc('helloWorldItIsMe') // 'hello World It Is Me'
Примерудаляем заглавные буквы
Теперь у нас есть строка с кучей ненужных прописных букв. Вы догадались, как их удалить? Во-первых, нам нужно выбрать все заглавные буквы. Затем используем поиск набора символов с помощью глобального модификатора:
//g
Мы снова будем использовать метод replace, но как в этот раз сделать строчной символ?
function lowerCase(str){ return str.replace(//g, ???); }
Подсказка: в методе replace() в качестве второго параметра можно указать функцию.
Мы будем использовать стрелочную функцию, чтобы не захватывать значение найденного совпадения. При использовании функции в методе JavaScript regexp replace эта функция будет вызвана после поиска совпадений, и результат функции используется в качестве замещающей строки. Еще лучше, если совпадение является глобальным и найдено несколько совпадений — функция будет вызвана для каждого найденного совпадения.
function lowerCase(str){ return str.replace(//g, (u) => u.toLowerCase()); } lowerCase('camel Case') // 'camel case' lowerCase('hello World It Is Me') // 'hello world it is me'
Пример: преобразуем первую букву в заглавную
capitalize('camel case') // => должен вернуть 'Camel case'
Еще раз воспользуемся функцией в методе replace(). Однако на этот раз нам нужно искать только первый символ в строке. Напомним, что для этого используется символ «^».
Давайте на секунду задержимся на символе «^». Вспомните пример, приведенный ранее:
console.log(/cat/.test('the cat says meow')); //верно
При добавлении символа «^» функция больше не возвращает значение true, поскольку слово «cat» находится не в начале строки:
console.log(/^cat/.test('the cat says meow')); //неверно
Мы хотим применить символ «^» к любому строчному символу в начале строки, поэтому мы поместим его перед набором символов . В этом случае JavaScript regexp будет направлено только на первый символ, если это строчная буква.
/^/
Обратите внимание, что мы больше не используем глобальный модификатор, так как нам нужно только одно совпадение. Теперь можно вставить регулярное выражение в метод replace и добавить стрелочную функцию в качестве второго аргумента:
function capitalize(str){ return str.replace(/^/, (u) => u.toUpperCase()); } capitalize('camel case') // 'Camel case' capitalize('hello world it is me') // 'Hello world it is me'
Операторы контроля
Ещё один вид специальных символов — это операторы контроля. Такие символы позволяют описывать шаблоны с границами, то есть указывать, где начинается или заканчивается слово или строка. С помощью операторов контроля также можно создавать более сложные шаблоны, такие как опережающие проверки, ретроспективные проверки и условные выражения.
/* Оператор контроля - Значение */^ - начало строки (последующее регулярное выражение должно совпадать с началом проверяемой строки).$ - конец строки (последующее регулярное выражение должно совпадать с концом проверяемой строки).\b - граница слова, то есть его начало или конец.\B - несловообразующая граница.x(?=y) - опережающая проверка. Совпадение с "x", только если за "x" следует "y".x(?!y) - негативная опережающая проверка. Совпадение с "x", только если за "x" не следует "y".(?<=y)x - ретроспективная проверка. Совпадение с "x", только если перед "x" стоит "y".(?<!y)x - негативная ретроспективная проверка. Совпадение с "x", только если перед "x" не стоит "y".
Примеры:
// ^ - Начало строкиconst myPattern = /^re/console.log(myPattern.test('write'))// falseconsole.log(myPattern.test('read'))// trueconsole.log(myPattern.test('real'))// trueconsole.log(myPattern.test('free'))// false// $ - Конец строкиconst myPattern = /ne$/console.log(myPattern.test('all is done'))// trueconsole.log(myPattern.test('on the phone'))// trueconsole.log(myPattern.test('in Rome'))// falseconsole.log(myPattern.test('Buy toner'))// false// \b - Граница словаconst myPattern = /\bro/console.log(myPattern.test('road'))// trueconsole.log(myPattern.test('steep'))// falseconsole.log(myPattern.test('umbro'))// false// Илиconst myPattern = /\btea\b/console.log(myPattern.test('tea'))// trueconsole.log(myPattern.test('steap'))// falseconsole.log(myPattern.test('tear'))// false// \B - Несловообразующая границаconst myPattern = /\Btea\B/console.log(myPattern.test('tea'))// falseconsole.log(myPattern.test('steap'))// trueconsole.log(myPattern.test('tear'))// false// x(?=y) - Опережающая проверкаconst myPattern = /doo(?=dle)/console.log(myPattern.test('poodle'))// falseconsole.log(myPattern.test('doodle'))// trueconsole.log(myPattern.test('moodle'))// false// x(?!y) - Негативная опережающая проверкаconst myPattern = /gl(?!u)/console.log(myPattern.test('glue'))// falseconsole.log(myPattern.test('gleam'))// true// (?<=y)x - Ретроспективная проверкаconst myPattern = /(?<=re)a/console.log(myPattern.test('realm'))// trueconsole.log(myPattern.test('read'))// trueconsole.log(myPattern.test('rest'))// false// (?<!y)x - Негативная ретроспективная проверкаconst myPattern = /(?<!re)a/console.log(myPattern.test('break'))// falseconsole.log(myPattern.test('treat'))// falseconsole.log(myPattern.test('take'))// true
МетаСимволы
Для указания регулярных выражений используются метасимволы. В приведенном выше примере ( ) является метасимволом.
Метасимволы — это символы, которые интерпретируются особым образом механизмом RegEx. Вот список метасимволов:
[]. ^ $ * +? {} () \ |
— Квадратные скобки
Квадратные скобки указывают набор символов, которые вы хотите сопоставить.
Выражение | Строка | Совпадения |
---|---|---|
1 совпадение | ||
2 совпадения | ||
Не совпадает | ||
5 совпадений |
Здесь будет соответствовать, если строка, которую вы пытаетесь сопоставить, содержит любой из символов , или .
Вы также можете указать диапазон символов, используя дефис в квадратных скобках.
то же самое, что и .
то же самое, что и .
то же самое, что и .
Вы можете дополСтрока (инвертировать) набор символов, используя символ вставки в начале квадратной скобки.
означает любой символ, кроме или или .
означает любой нецифровой символ.
— Точка
Точка соответствует любому одиночному символу (кроме новой строки ).
Выражение | Строка | Совпадения |
---|---|---|
Не совпадает | ||
1 совпадение | ||
1 совпадение | ||
2 совпадения (содержит 4 символа) |
— Каретка
Символ каретки используется для проверки того, начинается ли строка с определенного символа.
Выражение | Строка | Совпадения |
---|---|---|
1 совпадение | ||
1 совпадение | ||
Не совпадает | ||
1 совпадение | ||
Нет совпадений (начинается с , но не сопровождается ) |
— доллар
Символ доллара используется для проверки того, заканчивается ли строка определенным символом.
Выражение | Строка | Совпадения |
---|---|---|
1 совпадение | ||
1 совпадение | ||
Не совпадает |
— Звездочка
Символ звездочки соответствует предыдущему символу повторенному 0 или более раз. Эквивалентно {0,}.
Выражение | Строка | Совпадения |
---|---|---|
1 совпадение | ||
1 совпадение | ||
1 совпадение | ||
Нет совпадений ( не следует ) | ||
1 совпадение |
— Плюс
Символ плюс соответствует предыдущему символу повторенному 1 или более раз. Эквивалентно {1,}.
Выражение | Строка | Совпадения |
---|---|---|
Нет совпадений (нет символа) | ||
1 совпадение | ||
1 совпадение | ||
Нет совпадений ( не следует ) | ||
1 совпадение |
— Вопросительный знак
Знак вопроса соответствует нулю или одному вхождению предыдущего символа. То же самое, что и {0,1}. По сути, делает символ необязательным.
Выражение | Строка | Совпадения |
---|---|---|
1 совпадение (0 вхождений а) | ||
1 совпадение | ||
Нет совпадений (более одного символа) | ||
Нет совпадений ( не следует ) | ||
1 совпадение |
— Фигурные скобки
Рассмотрим следующий код: . Это означает, по крайней мере , и не больше повторений предыдущего символа. При m=n=1 пропускается..
Выражение | Строка | Совпадения |
---|---|---|
Не совпадает | ||
1 совпадение (в ) | ||
2 совпадения (при и ) | ||
2 совпадения (при и ) |
Посмотрим еще один пример. Это RegEx соответствует как минимум 2 цифрам, но не более 4-х цифр.
Выражение | Строка | Совпадения |
---|---|---|
1 совпадение (совпадение в ) | ||
3 совпадения ( , , ) | ||
Не совпадает |
— Альтернация (или)
Альтернация (вертикальная черта) – термин в регулярных выражениях, которому в русском языке соответствует слово «ИЛИ». (оператор ).
Например: gr(a|e)y означает точно то же, что и gry.
Выражение | Строка | Совпадения |
---|---|---|
Не совпадает | ||
1 совпадение (совпадение в ) | ||
3 совпадения (в ) |
Здесь сопоставьте любую строку, содержащую либо, либо
Чтобы примеСтрока альтернацию только к части шаблона, можно заключить её в скобки:
- найдёт или .
- найдёт или .
— Скобочные группы
Круглые скобки используются для группировки подшаблонов. Так, например, соответствует любой строке, которая соответствует либо или или с последующим
Выражение | Строка | Совпадения |
---|---|---|
Не совпадает | ||
1 совпадение (совпадение в ) | ||
2 совпадения (в ) |
— обратная косая черта
Обратная косая черта используется для экранирования различных символов, включая все метасимволы. Например,
соответствует, если строка содержит , за которым следует . Здесь механизм RegEx не интерпретирует особым образом.
Если вы не уверены, имеет ли символ особое значение или нет, вы можете экранировать его косой чертой . Это гарантирует, что экранированный символ не будет компилироваться по-особенному.
Упрощённый пример
В чём же дело? Почему регулярное выражение «зависает»?
Чтобы это понять, упростим пример: уберём из него пробелы . Получится .
И, для большей наглядности, заменим на . Получившееся регулярное выражение тоже будет «зависать», например:
В чём же дело, что не так с регулярным выражением?
Внимательный читатель, посмотрев на , наверняка удивится, ведь оно какое-то странное. Квантификатор здесь выглядит лишним. Если хочется найти число, то с тем же успехом можно искать .
Действительно, это регулярное выражение носит искусственный характер, но, разобравшись с ним, мы поймём и практический пример, данный выше. Причина их медленной работы одинакова. Поэтому оставим как есть.
Что же происходит во время поиска в строке (укоротим для ясности), почему всё так долго?
-
Первым делом, движок регулярных выражений пытается найти . Плюс является жадным по умолчанию, так что он хватает все цифры, какие может:
Затем движок пытается применить квантификатор , но больше цифр нет, так что звёздочка ничего не даёт.
Далее по шаблону ожидается конец строки , а в тексте символ , так что соответствий нет:
-
Так как соответствие не найдено, то «жадный» квантификатор уменьшает количество повторений, возвращается на один символ назад.
Теперь – это все цифры, за исключением последней:
-
Далее движок снова пытается продолжить поиск, начиная уже с позиции ().
Звёздочка теперь может быть применена – она даёт второе число :
Затем движок ожидает найти , но это ему не удаётся, ведь строка оканчивается на :
-
Так как совпадения нет, то поисковый движок продолжает отступать назад. Общее правило таково: последний жадный квантификатор уменьшает количество повторений до тех пор, пока это возможно. Затем понижается предыдущий «жадный» квантификатор и т.д.
Перебираются все возможные комбинации. Вот их примеры.
Когда первое число содержит 7 цифр, а дальше число из 2 цифр:
Когда первое число содержит 7 цифр, а дальше два числа по 1 цифре:
Когда первое число содержит 6 цифр, а дальше одно число из 3 цифр:
Когда первое число содержит 6 цифр, а затем два числа:
…И так далее.
Существует много способов как разбить на числа набор цифр . Если быть точным, их , где – длина набора.
В случае их порядка миллиона, при – ещё в тысячу раз больше. На их перебор и тратится время.
Что же делать?
Может нам стоит использовать «ленивый» режим?
К сожалению, нет: если мы заменим на , то регулярное выражение всё ещё будет «зависать». Поменяется только порядок перебора, но не общее количество комбинаций.
Некоторые движки регулярных выражений содержат хитрые проверки и конечные автоматы, которые позволяют избежать полного перебора в таких ситуациях или кардинально ускорить его, но не все движки и не всегда.
Создание регулярного выражения
Регулярное выражение JavaScript (или Regex ) — это последовательность символов, которую мы можем использовать для эффективной работы со строками. Используя этот синтаксис, мы можем:
- искать текст в строке
- заменить подстроки в строке
- извлекать информацию из строки
Регулярное выражение — это тип объекта. В JavaScript мы можем создать регулярное выражение двумя способами: либо с помощью конструктора RegExp, либо с помощью литерального синтаксиса.
Литеральный синтаксис использует косую черту ( /pattern/) для обертывания шаблона регулярного выражения, тогда как синтаксис конструктора использует кавычки ( «pattern»). В следующем примере демонстрируются оба способа создания регулярного выражения, которое соответствует любой строке, начинающейся с «Mr.».
ВыполСтрока код »
Скрыть результаты
В приведенном выше примере строка Mr. соответствует шаблону RegExp(«^Mr\\.»). Здесь для проверки соответствия строки шаблону используется метод test().
Есть несколько других методов, доступных для использования с JavaScript RegEx. Прежде чем мы их изучим, давайте узнаем о самих регулярных выражениях.
Примечание: При использовании синтаксиса конструктора необходимо дважды экранировать специальные символы, что означает соответствие «.» вам нужно писать «\\.»вместо «\.». Если есть только одна обратная косая черта, она будет интерпретирована парсером строк JavaScript как экранирующий символ и будет удалена.
К специальным символам регулярного выражения относятся: . Вам нужно будет использовать обратную косую черту для этих символов всякий раз, когда вы захотите использовать их буквально. Например, если вы хотите сопоставить «?», Вам нужно будет написать . Все остальные символы автоматически принимают их буквальные значения.
Поиск совпадений: метод exec
Метод возвращает массив и ставит свойства регулярного выражения.
Если совпадений нет, то возвращается null.
Например,
// Найти одну d, за которой следует 1 или более b, за которыми одна d // Запомнить найденные b и следующую за ними d // Регистронезависимый поиск var myRe = /d(b+)(d)/ig; var myArray = myRe.exec("cdbBdbsbz");
В результате выполнения скрипта будут такие результаты:
Объект | Свойство/Индекс | Описания | Пример |
Содержимое . | |||
Индекс совпадения (от 0) | |||
Исходная строка. | |||
Последние совпавшие символы | |||
Совпадения во вложенных скобках, если есть. Число вложенных скобок не ограничено. | |||
Индекс, с которого начинать следующий поиск. | |||
Показывает, что был включен регистронезависимый поиск, флаг «». | |||
Показывает, что был включен флаг «» поиска совпадений. | |||
Показывает, был ли включен флаг многострочного поиска «». | |||
Текст паттерна. |
Если в регулярном выражении включен флаг «», Вы можете вызывать метод много раз для поиска последовательных совпадений в той же строке. Когда Вы это делаете, поиск начинается на подстроке , с индекса . Например, вот такой скрипт:
var myRe = /ab*/g; var str = "abbcdefabh"; while ((myArray = myRe.exec(str)) != null) { var msg = "Found " + myArray + ". "; msg += "Next match starts at " + myRe.lastIndex; print(msg); }
Этот скрипт выведет следующий текст:
Found abb. Next match starts at 3 Found ab. Next match starts at 9
В следующем примере функция выполняет поиск по input. Затем делается цикл по массиву, чтобы посмотреть, есть ли другие имена.
Предполагается, что все зарегистрированные имена находятся в массиве А:
var A = ; function lookup(input) { var firstName = /\w+/i.exec(input); if (!firstName) { print(input + " isn't a name!"); return; } var count = 0; for (var i = 0; i < A.length; i++) { if (firstName.toLowerCase() == A.toLowerCase()) count++; } var midstring = (count == 1) ? " other has " : " others have "; print("Thanks, " + count + midstring + "the same name!") }
Create a RegEx
There are two ways you can create a regular expression in JavaScript.
-
Using a regular expression literal:
The regular expression consists of a pattern enclosed between slashes . For example,Here, is a regular expression.
-
Using the constructor function:
You can also create a regular expression by calling the constructor function. For example,
For example,
In the above example, the string matches with the RegEx pattern . Here, the method is used to check if the string matches the pattern.
There are several other methods available to use with JavaScript RegEx. Before we explore them, let’s learn about regular expressions themselves.
If you already know the basics of RegEx, jump to .
Строковые методы, поиск и замена
Следующие методы работают с регулярными выражениями из строк.
Все методы, кроме replace, можно вызывать как с объектами типа regexp в аргументах, так и со строками, которые автоматом преобразуются в объекты RegExp.
Так что вызовы эквивалентны:
var i = str.search(/\s/) var i = str.search("\\s")
При использовании кавычек нужно дублировать \ и нет возможности указать флаги. Если регулярное выражение уже задано строкой, то бывает удобна и полная форма
var regText = "\\s" var i = str.search(new RegExp(regText, "g"))
Возвращает индекс регулярного выражения в строке, или -1.
Если Вы хотите знать, подходит ли строка под регулярное выражение, используйте метод (аналогично RegExp-методы ). Чтобы получить больше информации, используйте более медленный метод (аналогичный методу ).
Этот пример выводит сообщение, в зависимости от того, подходит ли строка под регулярное выражение.
function testinput(re, str){ if (str.search(re) != -1) midstring = " contains "; else midstring = " does not contain "; document.write (str + midstring + re.source); }
Если в regexp нет флага , то возвращает тот же результат, что .
Если в regexp есть флаг , то возвращает массив со всеми совпадениями.
Чтобы просто узнать, подходит ли строка под регулярное выражение , используйте .
Если Вы хотите получить первый результат — попробуйте r.
В следующем примере используется, чтобы найти «Chapter», за которой следует 1 или более цифр, а затем цифры, разделенные точкой. В регулярном выражении есть флаг , так что регистр будет игнорироваться.
str = "For more information, see Chapter 3.4.5.1"; re = /chapter (\d+(\.\d)*)/i; found = str.match(re); alert(found);
Скрипт выдаст массив из совпадений:
- Chapter 3.4.5.1 — полностью совпавшая строка
- 3.4.5.1 — первая скобка
- .1 — внутренняя скобка
Следующий пример демонстрирует использование флагов глобального и регистронезависимого поиска с . Будут найдены все буквы от А до Е и от а до е, каждая — в отдельном элементе массива.
var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; var regexp = //gi; var matches = str.match(regexp); document.write(matches); // matches =
Метод replace может заменять вхождения регулярного выражения не только на строку, но и на результат выполнения функции. Его полный синтаксис — такой:
var newString = str.replace(regexp/substr, newSubStr/function)
- Объект RegExp. Его вхождения будут заменены на значение, которое вернет параметр номер 2
- Строка, которая будет заменена на .
- Строка, которая заменяет подстроку из аргумента номер 1.
- Функция, которая может быть вызвана для генерации новой подстроки (чтобы подставить ее вместо подстроки, полученной из аргумента 1).
Метод не меняет строку, на которой вызван, а просто возвращает новую, измененную строку.
Чтобы осуществить глобальную замену, включите в регулярное выражение флаг .
Если первый аргумент — строка, то она не преобразуется в регулярное выражение, так что, например,
var ab = "a b".replace("\\s","..") // = "a b"
Вызов replace оставил строку без изменения, т.к искал не регулярное выражение , а строку «\s».
В строке замены могут быть такие спецсимволы:
Pattern | Inserts |
Вставляет «$». | |
Вставляет найденную подстроку. | |
Вставляет часть строки, которая предшествует найденному вхождению. | |
Вставляет часть строки, которая идет после найденного вхождения. | |
or | Где или — десятичные цифры, вставляет подстроку вхождения, запомненную -й вложенной скобкой, если первый аргумент — объект RegExp. |
Если Вы указываете вторым параметром функцию, то она выполняется при каждом совпадении.
В функции можно динамически генерировать и возвращать строку подстановки.
Первый параметр функции — найденная подстрока. Если первым аргументом является объект , то следующие параметров содержат совпадения из вложенных скобок. Последние два параметра — позиция в строке, на которой произошло совпадение и сама строка.
Например, следующий вызов возвратит XXzzzz — XX , zzzz.
function replacer(str, p1, p2, offset, s) { return str + " - " + p1 + " , " + p2; } var newString = "XXzzzz".replace(/(X*)(z*)/, replacer)
Как видите, тут две скобки в регулярном выражении, и потому в функции два параметра , .
Если бы были три скобки, то в функцию пришлось бы добавить параметр .
Следующая функция заменяет слова типа на :
function styleHyphenFormat(propertyName) { function upperToHyphenLower(match) { return '-' + match.toLowerCase(); } return propertyName.replace(//, upperToHyphenLower); }