Регулярные выражения (объект RegExp). Объект RegExp. Регулярные выражения Javascript replace регулярные выражения
В JavaScript регулярные выражения представлены объектами RegExp . Объекты RegExp могут быть созданы посредством конструктора RegExp(), но чаще они создаются с помощью специального синтаксиса литералов. Так же как строковые литералы задаются в виде символов, заключенных в кавычки, литералы регулярных выражений задаются в виде символов, заключенных в пару символов слэша / .
/pattern/флаги new RegExp("pattern"[, опции поиска])
pattern - регулярное выражение для поиска (о замене - позже), а флаги - строка из любой комбинации символов g(глобальный поиск), i(регистр неважен) и m(многострочный поиск). Первый способ используется часто, второй - иногда. Например, два таких вызова эквивалентны.
Опции поиска
При создании регулярного выражения мы можем указать дополнительных опции поиска
Символы в регулярных выражениях JavaScript
Символ | Соответствие |
---|---|
Алфавитно-цифровые символы | Соответствуют сами себе |
\0 | Символ NUL (\u0000) |
\t | Табуляция (\u0009) |
\n | Перевод строки (\u000A) |
\v | Вертикальная табуляция (\u000B) |
\f | Перевод страницы (\u000C) |
\r | Возврат каретки (\u000D) |
\xnn | Символ из набора Latin, задаваемый шестнадцатеричным числом nn; например, \x0A - это то же самое, что \n |
\uxxxx | Unicode-символ, заданный шестнадцатеричным числом xxxx; например, \u0009 - это то же самое, что \t |
\cX | Управляющий символ "X", например, последовательность \cJ эквивалентна символу перевода строки \n |
\ | Для обычных символов - делает их специальными. Например, выражение /s/ ищет просто символ "s". А если поставить \ перед s, то /\s/ уже обозначает пробельный символ.И наоборот, если символ специальный, например *, то \ сделает его просто обычным символом "звездочка". Например, /a*/ ищет 0 или больше подряд идущих символов "a". Чтобы найти а со звездочкой "a*" - поставим \ перед спец. символом: /a\*/ . |
^ | Обозначает начало входных данных. Если установлен флаг многострочного поиска ("m") , то также сработает при начале новой строки.Например, /^A/ не найдет "A" в "an A", но найдет первое "A" в "An A." |
$ | Обозначает конец входных данных. Если установлен флаг многострочного поиска, то также сработает в конце строки.Например, /t$/ не найдет "t" в "eater", но найдет - в "eat". |
* | Обозначает повторение 0 или более раз. Например, /bo*/ найдет "boooo" в "A ghost booooed" и "b" в "A bird warbled", но ничего не найдет в "A goat grunted". |
+ | Обозначает повторение 1 или более раз. Эквивалентно {1,} . Например, /a+/ найдет "a" в "candy" и все "a" в "caaaaaaandy". |
? | Обозначает, что элемент может как присутствовать, так и отсутствовать. Например, /e?le?/ найдет "el" в "angel" и "le" в "angle."Если используется сразу после одного из квантификаторов * , + , ? , или {} , то задает "нежадный" поиск (повторение минимально возможное количество раз, до ближайшего следующего элемента паттерна), в противоположность "жадному" режиму по умолчанию, при котором количество повторений максимально, даже если следующий элемент паттерна тоже подходит.Кроме того, ? используется в предпросмотре, который описан в таблице под (?=) , (?!) , и (?:) . |
. | (Десятичная точка) обозначает любой символ, кроме перевода строки: \n \r \u2028 or \u2029. (можно использовать [\s\S] для поиска любого символа, включая переводы строк). Например, /.n/ найдет "an" и "on" в "nay, an apple is on the tree", но не "nay". |
(x) | Находит x и запоминает. Это называется "запоминающие скобки". Например, /(foo)/ найдет и запомнит "foo" в "foo bar." Найденная подстрока хранится в массиве-результате поиска или в предопределенных свойствах объекта RegExp: $1, ..., $9 .Кроме того, скобки объединяют то, что в них находится, в единый элемент паттерна. Например, (abc)* - повторение abc 0 и более раз. |
(?:x) | Находит x , но не запоминает найденное. Это называется "незапоминающие скобки". Найденная подстрока не сохраняется в массиве результатов и свойствах RegExp.Как и все скобки, объединяют находящееся в них в единый подпаттерн. |
x(?=y) | Находит x , только если за x следует y . Например, /Jack(?=Sprat)/ найдет "Jack", только если за ним следует "Sprat". /Jack(?=Sprat|Frost)/ найдет "Jack", только если за ним следует "Sprat" или "Frost". Однако, ни "Sprat" ни "Frost" не войдут в результат поиска. |
x(?!y) | Находит x , только если за x не следует y . Например, /\d+(?!\.)/ найдет число, только если за ним не следует десятичная точка. /\d+(?!\.)/.exec("3.141") найдет 141, но не 3.141. |
x|y | Находит x или y . Например, /green|red/ найдет "green" в "green apple" и "red" в "red apple." |
{n} | Где n - положительное целое число. Находит ровно n повторений предшествующего элемента. Например, /a{2}/ не найдет "a" в "candy," но найдет оба a в "caandy," и первые два a в "caaandy." |
{n,} | Где n - положительное целое число. Находит n и более повторений элемента. Например, /a{2,} не найдет "a" в "candy", но найдет все "a" в "caandy" и в "caaaaaaandy." |
{n,m} | Где n и m - положительные целые числа. Находят от n до m повторений элемента. |
Набор символов. Находит любой из перечисленных символов. Вы можете указать промежуток, используя тире. Например, - то же самое, что . Найдет "b" в "brisket", а также "a" и "c" в "ache". | |
[^xyz] | Любой символ, кроме указанных в наборе. Вы также можете указать промежуток. Например, [^abc] - то же самое, что [^a-c] . Найдет "r" в "brisket" и "h" в "chop." |
[\b] | Находит символ backspace. (Не путать с \b .) |
\b | Находит границу слов (латинских), например пробел. (Не путать с [\b]). Например, /\bn\w/ найдет "no" в "noonday"; /\wy\b/ найдет "ly" в "possibly yesterday." |
\B | Обозначает не границу слов. Например, /\w\Bn/ найдет "on" в "noonday", а /y\B\w/ найдет "ye" в "possibly yesterday." |
\cX | Где X - буква от A до Z. Обозначает контрольный символ в строке. Например, /\cM/ обозначает символ Ctrl-M. |
\d | находит цифру из любого алфавита (у нас же юникод). Испльзуйте , чтобы найти только обычные цифры. Например, /\d/ или // найдет "2" в "B2 is the suite number." |
\D | Найдет нецифровой символ (все алфавиты). [^0-9] - эквивалент для обычных цифр. Например, /\D/ или /[^0-9]/ найдет "B" в "B2 is the suite number." |
\s | Найдет любой пробельный символ, включая пробел, табуляцию, переводы строки и другие юникодные пробельные символы. Например, /\s\w*/ найдет " bar" в "foo bar." |
\S | Найдет любой символ, кроме пробельного. Например, /\S\w*/ найдет "foo" в "foo bar." |
\v | Символ вертикальной табуляции. |
\w | Найдет любой словесный (латинский алфавит) символ, включая буквы, цифры и знак подчеркивания. Эквивалентно . Например, /\w/ найдет "a" в "apple," "5" в "$5.28," и "3" в "3D." |
\W | Найдет любой не-(лат.)словесный символ. Эквивалентно [^A-Za-z0-9_] . Например, /\W/ и /[^$A-Za-z0-9_]/ одинаково найдут "%" в "50%." |
Работа с регулярными выражениями в Javascript
Работа с регулярными выражениями в Javascript реализована методами класса String
exec(regexp) - находит все совпадения (вхождения в шаблон "регулярки") в строке. Возвращает массив (при совпадении) и обновляет свойство regexp-а, или null - если ничего не найдено,. С модификатором g - при каждом вызове этой функции, она будет возвращать следующее совпадение после предыдущего найденного - это реализовано с помощью ведения индекса смещения последнего поиска.
match(regexp) - найти часть строки по шаблону. Если указан модификатор g, то функция match() возвращает массив всех совпадений или null (а не пустой массив). Без модификатора g эта функция работает как exec();
test(regexp) - функция проверяет строку на соответствие шаблону. Возвращает true - если есть совпадение, и false - если совпадения нет.
split(regexp) - разбивает строку, для которой он вызван, на массив подстрок, используя аргумент в качестве разделителя.
replace(regexp, mix) - метод возвращает строку изменную в соответствии с шаблоном (регуляррным выражением). Первый параметр regexp также может содержать строку, а не регулярное выражение. Без модификатора g - метод в строке заменяет только первое вхождение; с модификатором g - происходит глобальная замена, т.е. меняются все вхождения в данной строке. mix - шаблон замены, может принитать значения строки, шаблона замены, функции (имя функции).
Спецсимволы в строке замены
Замена через функцию
Если Вы указываете вторым параметром функцию, то она выполняется при каждом совпадении. В функции можно динамически генерировать и возвращать строку подстановки. Первый параметр функции - найденная подстрока. Если первым аргументом replace является объект RegExp, то следующие n параметров содержат совпадения из вложенных скобок. Последние два параметра - позиция в строке, на которой произошло совпадение и сама строка.
Регулярные выражения позволяют производить гибкий поиск в строках текста.
Создание
var expr = new RegExp(pattern [, flags]); // полная форма записи var expr = /pattern/flags; // сокращенная форма записи (литеральный формат)Параметры
pattern Шаблон поиска (текст регулярного выражения). flags Способы поиска по шаблону:- g - глобальный поиск (обрабатываются все совпадения с шаблоном поиска);
- i - не различать строчные и заглавные буквы;
- m - многострочный поиск.
Комментарии
Когда регулярное выражение создается при помощи конструктора new RegExp(…) , необходимо помнить, что обратные слеши (\) должны экранироваться, например:
Var expr = new RegExp("\\w", "ig");
При использовании литерального формата, этого делать не нужно:
Var expr = /\w/gi;
Обе записи эквивалентны. Первый вариант может понадобится, если вам придется генерировать регулярное выражение динамически.
В регулярных выражениях различают следующие виды символов:
Обычные символы
Специальные символы
Спецсимволы в регулярном выражении
Символ | Значение |
---|---|
\ | Для обычных символов - делает их специальными. Например, выражение /s/ ищет просто символ "s". А если поставить \ перед s, то /\s/ уже обозначает пробельный символ. И наоборот, если символ специальный, например *, то \ сделает его просто обычным символом "звездочка". Например, /a*/ ищет 0 или больше подряд идущих символов "a". Чтобы найти а со звездочкой "a*" - поставим \ перед спец. символом: /a\*/ . |
^ | Обозначает начало входных данных. Если установлен флаг многострочного поиска ("m") , то также сработает при начале новой строки. Например, /^A/ не найдет "A" в "an A", но найдет первое "A" в "An A." |
$ | Обозначает конец входных данных. Если установлен флаг многострочного поиска, то также сработает в конце строки. Например, /t$/ не найдет "t" в "eater", но найдет - в "eat". |
* | Обозначает повторение 0 или более раз. Например, /bo*/ найдет "boooo" в "A ghost booooed" и "b" в "A bird warbled", но ничего не найдет в "A goat grunted". |
+ | Обозначает повторение 1 или более раз. Эквивалентно {1,} . Например, /a+/ найдет "a" в "candy" и все "a" в "caaaaaaandy". |
? | Обозначает, что элемент может как присутствовать, так и отсутствовать. Например, /e?le?/ найдет "el" в "angel" и "le" в "angle."Если используется сразу после одного из квантификаторов * , + , ? , или {} , то задает "нежадный" поиск (повторение минимально возможное количество раз, до ближайшего следующего элемента паттерна), в противоположность "жадному" режиму по умолчанию, при котором количество повторений максимально, даже если следующий элемент паттерна тоже подходит. Кроме того, ? используется в предпросмотре, который описан в таблице под (?=) , (?!) , и (?:) . |
. | (Десятичная точка) обозначает любой символ, кроме перевода строки: \n \r \u2028 or \u2029. (можно использовать [\s\S] для поиска любого символа, включая переводы строк). Например, /.n/ найдет "an" и "on" в "nay, an apple is on the tree", но не "nay". |
(x) | Находит x и запоминает. Это называется "запоминающие скобки". Например, /(foo)/ найдет и запомнит "foo" в "foo bar." Найденная подстрока хранится в массиве-результате поиска или в предопределенных свойствах объекта RegExp: $1, ..., $9 . Кроме того, скобки объединяют то, что в них находится, в единый элемент паттерна. Например, (abc)* - повторение abc 0 и более раз. |
(?:x) | Находит x , но не запоминает найденное. Это называется "незапоминающие скобки". Найденная подстрока не сохраняется в массиве результатов и свойствах RegExp. Как и все скобки, объединяют находящееся в них в единый подпаттерн. |
x (?= y) | Находит x , только если за x следует y . Например, /Jack(?=Sprat)/ найдет "Jack", только если за ним следует "Sprat". /Jack(?=Sprat|Frost)/ найдет "Jack", только если за ним следует "Sprat" или "Frost". Однако, ни "Sprat" ни "Frost" не войдут в результат поиска. |
x (?! y) | Находит x , только если за x не следует y . Например, /\d+(?!\.)/ найдет число, только если за ним не следует десятичная точка. /\d+(?!\.)/.exec("3.141") найдет 141, но не 3.141. |
x | y | Находит x или y . Например, /green|red/ найдет "green" в "green apple" и "red" в "red apple." |
{n} | Где n - положительное целое число. Находит ровно n повторений предшествующего элемента. Например, /a{2}/ не найдет "a" в "candy," но найдет оба a в "caandy," и первые два a в "caaandy." |
{n,} | Где n - положительное целое число. Находит n и более повторений элемента. Например, /a{2,} не найдет "a" в "candy", но найдет все "a" в "caandy" и в "caaaaaaandy." |
{n,m} | Где n и m - положительные целые числа. Находят от n до m повторений элемента. |
Набор символов. Находит любой из перечисленных символов. Вы можете указать промежуток, используя тире. Например, - то же самое, что . Найдет "b" в "brisket" и "c" в "ache". | |
[^xyz] | Любой символ, кроме указанных в наборе. Вы также можете указать промежуток. Например, [^abc] - то же самое, что [^a-c] . Найдет "r" в "brisket" и "h" в "chop." |
[\b] | Находит символ backspace. (Не путать с \b .) |
\b | Находит границу слов (латинских), например пробел. (Не путать с [\b]). Например, /\bn\w/ найдет "no" в "noonday"; /\wy\b/ найдет "ly" в "possibly yesterday." |
\B | Обозначает не границу слов. Например, /\w\Bn/ найдет "on" в "noonday", а /y\B\w/ найдет "ye" в "possibly yesterday." |
\cX | Где X - буква от A до Z. Обозначает контрольный символ в строке. Например, /\cM/ обозначает символ Ctrl-M. |
\d | находит цифру из любого алфавита (у нас же юникод). Используйте , чтобы найти только обычные цифры. Например, /\d/ или // найдет "2" в "B2 is the suite number." |
\D | Найдет нецифровой символ (все алфавиты). [^0-9] - эквивалент для обычных цифр. Например, /\D/ или /[^0-9]/ найдет "B" в "B2 is the suite number." |
\f,\r,\n | Соответствующие спецсимволы form-feed, line-feed, перевод строки. |
\s | Найдет любой пробельный символ, включая пробел, табуляцию, переводы строки и другие юникодные пробельные символы. Например, /\s\w*/ найдет " bar" в "foo bar." |
\S | Найдет любой символ, кроме пробельного. Например, /\S\w*/ найдет "foo" в "foo bar." |
\t | Символ табуляции. |
\v | Символ вертикальной табуляции. |
\w | Найдет любой словесный (латинский алфавит) символ, включая буквы, цифры и знак подчеркивания. Эквивалентно . Например, /\w/ найдет "a" в "apple," "5" в "$5.28," и "3" в "3D." |
\W | Найдет любой не-(лат.)словесный символ. Эквивалентно [^A-Za-z0-9_] . Например, /\W/ и /[^$A-Za-z0-9_]/ одинаково найдут "%" в "50%." |
\n | где n - целое число. Обратная ссылка на n-ю запомненную скобками подстроку. Например, /apple(,)\sorange\1/ найдет "apple, orange," в "apple, orange, cherry, peach.". За таблицей есть более полный пример. |
\0 | Найдет символ NUL. Не добавляйте в конец другие цифры. |
\xhh | Найдет символ с кодом hh (2 шестнадцатиричных цифры) |
\uhhhh | Найдет символ с кодом hhhh (4 шестнадцатиричных цифры). |
Пример изменения формата строки
Var re = /(\w+)\s(\w+)/; var str = "John Smith"; var newstr = str.replace(re, "$2, $1"); alert(newstr); // "Smith, John"
Свойства
Методы
Выполняет поиск совпадения в своём строковом параметре. | |
Тестирует на совпадение в своём строковом параметре. | |
А также методы объекта String |
|
match | Выполняет поиск совпадения в строке. Возвращает массив информации, или null при отсутствии совпадения. |
search | Тестирует на наличие совпадений в строке. Возвращает индекс совпадения или -1, если поиск завершился неудачно. |
replace | Выполняет поиск совпадения в строке и заменяет найденные подстроки замещающей подстрокой. |
split | Использует регулярное выражение или фиксированную строку для разделения строки на массив подстрок. |
global
Используется ли флаг "g " в регулярном выражении.
Синтаксис
regexp.globalglobal
Значение global будет true , если флаг "g g
//Определим произвольное регулярное выражение var regexp = /Шаблон пример/g; /* В случае если regexp содержит модификатор g выведем "Модификатор g установлен", в противном случае выведем "Модификатор g не установлен" */ if (regexp.global) alert("Модификатор g установлен"); else alert("Модификатор g не установлен");
ignoreCase
Используется ли флаг "i " в регулярном выражении.
Синтаксис
regexp.ignoreCaseОписание, комментарии, примеры
ignoreCase это свойство отдельного объекта регулярного выражения.
Вы не можете изменять это свойство явно.
Значение ignoreCase будет true , если флаг "i " используется; иначе - false . Флаг "i " указывает, что регистр символов должен игнорироваться при поиске совпадений в строке.
//Определим произвольное регулярное выражение var regexp = /Шаблон пример/i; /* В случае если regexp содержит модификатор i выведем "Модификатор i установлен", в противном случае выведем "Модификатор i не установлен" */ if (regexp.ignoreCase) alert("Модификатор i установлен"); else alert("Модификатор i не установлен");
lastIndex
Свойство lastIndex указывает позицию, с которой начнется следующий поиск.
Синтаксис
regexp.lastIndexКомментарии
Это свойство будет работать только если в регулярном выражении установлен модификатор g .
Данное свойство возвращает целое число, которое обозначает позицию последнего символа найденного с помощью метода или .
Пример
//Определим произвольное регулярное выражение var str = "Я короткая строка"; //Зададим регулярное выражение var regexp = /о/g; //Совершим глобальный поиск "o" в строке текста и будем отображать //позицию после каждого найденного совпадения while (regexp.test(str)==true) { alert(regexp.lastIndex); }multiline
Используется ли флаг "m " в регулярном выражении.
Синтаксис
regexp.globalОписание, комментарии, примеры
multiline это свойство отдельного объекта регулярного выражения.
Вы не можете изменять это свойство явно.
Значение multiline будет true , если флаг "g " используется; иначе - false . Флаг "g " указывает, что регулярное выражение должно проверяться относительно всех возможных совпадений в строке.
//Определим произвольное регулярное выражение var regexp = /Шаблон пример/m; /* В случае если regexp содержит модификатор g выведем "Модификатор g установлен", в противном случае выведем "Модификатор g не установлен" */ if (regexp.multiline) alert("Модификатор m установлен"); else alert("Модификатор g не установлен");
source
Свойство source возвращает содержимое шаблона регулярного выражения
JavaScript regexp – это тип объекта, который используется для сопоставления последовательности символов в строках.
Создаем первое регулярное выражение
Существует два способа создания регулярного выражения: с использованием литерала регулярного выражения или с помощью конструктора регулярных выражений. Каждый из них представляет один и тот же шаблон: символ «c », за которым следует «a », а затем символ «t ».
// литерал регулярного выражения заключается в слэши (/) var option1 = /cat/; // Конструктор регулярнго выражения var option2 = new RegExp("cat");
Как правило, если регулярное выражение остается константой, то есть не будет меняться, лучше использовать литерал регулярного выражения. Если оно будет меняться или зависит от других переменных, лучше использовать метод с конструктором.
Метод RegExp.prototype.test()
Помните, я говорил, что регулярные выражения являются объектами? Это означает, что у них есть ряд методов. Самый простой метод – это JavaScript regexp test , который возвращает логическое значение:
True (истина ): строка содержит шаблон регулярного выражения.
False (ложь ): совпадения не найдено.
console.log(/cat/.test(“the cat says meow”)); // верно console.log(/cat/.test(“the dog says bark”)); // неверно
Памятка по основам регулярных выражений
Секрет регулярных выражений заключается в запоминании типовых символов и групп. Я настоятельно рекомендую потратить несколько часов на таблицу, приведенную ниже, а затем вернуться, и продолжить изучение.
Символы
- . – (точка ) соответствует любому одиночному символу за исключением переноса строки;
- * – соответствует предыдущему выражению, которое повторяется 0 или более раз;
- + – соответствует предыдущему выражению, которое повторяется 1 или более раз;
- ? – предыдущее выражение является необязательным (соответствует 0 или 1 раз );
- ^ – соответствует началу строки;
- $ – соответствует концу строки.
Группы символов
- d – соответствует любому одиночному цифровому символу.
- w – соответствует любому символу (цифре, букве или знаку подчёркивания).
- [XYZ ] – набор символов. Соответствует любому одиночному символу из набора, заданного в скобках. Также можно задавать и диапазоны символов, например, .
- [XYZ ]+ – соответствует символу из набора, повторяемого один или более раз.
- [^A —Z ] – внутри набора символов «^ » используется как знак отрицания. В данном примере шаблону соответствует всё, что не является буквами в верхнем регистре.
Флаги :
В JavaScript regexp существует пять необязательных флагов. Они могут использоваться отдельно или вместе, и размещаются после закрывающего слеша. Например: /[A —Z ]/g . Здесь я приведу только два флага.
g – глобальный поиск.
i – поиск, нечувствительный к регистру.
Дополнительные конструкции
(x ) – захватывающие скобки. Это выражение соответствует x и запоминает это соответствие, поэтому им можно воспользоваться позже.
(?:x ) – незахватывающие скобки. Выражение соответствует x , но не запоминает это соответствие.
Соответствует x , только если за ним следует y .
Протестируем изученный материал
Сначала протестируем все выше сказанное. Допустим, что мы хотим проверить строку на наличие любых цифр. Для этого можно использовать конструкцию «d ».
console.log(/d/.test("12-34")); // верно
Приведенный выше код возвращает значение true , если в строке есть хотя бы одна цифра. Что делать, если нужно проверить строку на соответствие формату? Можно использовать несколько символов «d », чтобы определить формат:
console.log(/dd-dd/.test("12-34")); //верно console.log(/dd-dd/.test("1234")); //неверно
Если неважно, как в JavaScript regexp online идут цифры до и после знака «— », можно использовать символ «+ », чтобы показать, что шаблон «d » встречается один или несколько раз:
console.log(/d+-d+/.test("12-34")); // верно console.log(/d+-d+/.test("1-234")); // верно console.log(/d+-d+/.test("-34")); // неверно
Для простоты можно использовать скобки, чтобы сгруппировать выражения. Допустим, у нас есть мяуканье кошки, и мы хотим проверить соответствие шаблону «meow » (мяу ):
console.log(/me+(ow)+w/.test("meeeeowowoww")); // верно
Теперь давайте разберемся.
m => соответствие одной букве ‘m ‘;
e + => соответствие букве «e» один или несколько раз;
(ow) + => соответствие буквам «ow» один или несколько раз;
w => соответствие букве ‘w ’;
‘m’ + ‘eeee’ + ‘owowow’ + ‘w’ .
Когда операторы типа «+ » используются сразу после скобок, они влияют на все содержимое скобок.
Оператор «? ». Он указывает, что предыдущий символ является необязательным. Как вы увидите ниже, оба тестовых примера возвращают значение true , потому что символы «s » помечены как необязательные.
console.log(/cats? says?/i.test("the Cat says meow")); //верно console.log(/cats? says?/i.test("the Cats say meow")); //верно
Если вы захотите найти символ слеша, нужно экранизировать его с помощью обратного слеша. То же самое верно для других символов, которые имеют особое значение, например, вопросительного знака. Вот JavaScript regexp пример того, как их искать:
var slashSearch = ///; var questionSearch = /?/;
- d – это то же самое, что и : каждая конструкция соответствует цифровому символу.
- w – это то же самое, что [A —Za —z 0-9_] : оба выражения соответствуют любому одиночному алфавитно-цифровому символу или подчеркиванию.
Пример: добавляем пробелы в строки, написанные в «верблюжьем» стиле
В этом примере мы очень устали от «верблюжьего » стиля написания и нам нужен способ добавить пробелы между словами. Вот пример:
removeCc("camelCase") // => должен вернуть "camel Case"
Существует простое решение с использованием регулярного выражения. Во-первых, нам нужно найти все заглавные буквы. Это можно сделать с помощью поиска набора символов и глобального модификатора.
Это соответствует символу «C » в «camelCase »
Теперь, как добавить пробел перед «C »?
Нам нужно использовать захватывающие скобки! Они позволяют найти соответствие и запомнить его, чтобы использовать позже! Используйте захватывающие скобки, чтобы запомнить найденную заглавную букву:
Получить доступ к захваченному значению позднее можно так:
Выше мы используем $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"
Пример: удаляем заглавные буквы
Теперь у нас есть строка с кучей ненужных прописных букв. Вы догадались, как их удалить? Во-первых, нам нужно выбрать все заглавные буквы. Затем используем поиск набора символов с помощью глобального модификатора:
Мы снова будем использовать метод 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"
Класс RegExp в JavaScript представляет собой регулярные выражения – объект, описывающий символьный шаблон. Объекты RegExp , как правило, создаются с помощью специального синтаксиса литералов, представленного ниже, но так же могут быть созданы посредством конструктора RegExp().
Синтаксис
// с помощью специального синтаксиса литералов var regex = /pattern /flags ; // с помощью конструктора var regex = new RegExp("pattern ", "flags "); var regex = new RegExp(/pattern /, "flags ");Значения параметров:
Флаги регулярных выражений
Флаг | Описание |
---|---|
g | Позволяет найти все совпадения, а не останавливаться после первого совпадения (global match flag ). |
i | Позволяет выполнить сопоставление без учета регистра (ignore case flag ). |
m | Сопоставление производится по нескольким строкам. Обработка начальных и конечных символов (^ и $) производится по нескольким строкам, то есть сопоставление происходит с началом или концом каждой строки (разделители \n или \r), а не только с началом, или концом всей строки (multiline flag ). |
u | Шаблон будет расценен как последовательность кодовых точек Юникода (unicode flag ). |
y | Сопоставление происходит по индексу на который указывает свойство lastIndex этого регулярного выражения, при этом сопоставление не производиться по более позднему, или раннему индексу (sticky flag ). |
Наборы символов
Метасимволы
Символ | Описание |
---|---|
. | Позволяет найти один символ, кроме символа новой строки, или символа конца строки (\n, \r, \u2028 или \u2029). |
\d | Позволяет найти символ цифры в базовом латинском алфавите. Эквивалентин использованию набору символов . |
\D | Позволяет найти любой символ, который не является цифрой в базовом латинском алфавите. Эквивалентен набору символов [^0-9]. |
\s | Позволяет найти одиночный пробельный символ. Под пробельным символом понимается пробел, табуляция, перевод страницы, перевод строки и другие пробельные символы Юникода. Эквивалентен набору символов [\f\n\r\t\v\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]. |
\S | Позволяет найти одиночный символ, который не является пробельным. Под пробельным символом понимается пробел, табуляция, перевод страницы, перевод строки и другие пробельные символы Юникода. Эквивалентен набору символов [^ \f\n\r\t\v\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]. |
[\b] | Позволяет найти символ backspace (специальный символ \b, U+0008). |
\0 | Позволяет найти символ 0 (ноль). |
\n | Позволяет найти символ новой строки. |
\f | Позволяет найти символ перевода страницы. |
\r | Позволяет найти символ возврата каретки. |
\t | Позволяет найти символ горизонтальной табуляции. |
\v | Позволяет найти символ вертикальной табуляции. |
\w | Позволяет найти любой буквенно-цифровой символ базового латинского алфавита, включая подчеркивание. Эквивалентен набору символов . |
\W | Позволяет найти любой символ, который не является символом из базового латинского алфавита. Эквивалентен набору символов [^a-Za-z0-9_]. |
\cX | Позволяет найти контрольный символ в строке. Где X - буква от A до Z. Например, /\cM/ обозначает символ Ctrl-M. |
\xhh | Позволяет найти символ, используя шестнадцатеричное значение (hh - двухзначное шестнадцатеричное значение). |
\uhhhh | Позволяет найти символ, используя кодировку UTF-16 (hhhh - четырехзначное шестнадцатеричное значение). |
\u{hhhh} или \u{hhhhh} | Позволяет найти символ со значением Юникода U+hhhh или U+hhhhh (шестнадцатеричное значение). Только когда задан флаг u . |
\ | Указывает, что следующий символ является специальным и не должен интерпретироваться буквально. Для символов, которые обычно трактуются специальным образом, указывает, что следующий символ не является специальным и должен интерпретироваться буквально. |
Ограничения
Квантификаторы
Символ | Описание |
---|---|
n* | Сопостовление происходит с любой строкой, содержащей ноль или более вхождений символа n . |
n+ | Сопостовление происходит с любой строкой, содержащей хотя бы один символ n . |
n? | Сопостовление происходит с любой строкой с предшествующим элементом n ноль или один раз. |
n{x} | Соответствует любой строке, содержащей последовательность символов n определенное количество раз x . X |
n{x,} | x вхождений предшествующего элемента n . X должно быть целым положительным числом. |
n{x, y} | Соответствует любой строке, содержащей по крайней мере x , но не более, чем с y вхождениями предшествующего элемента n . X и y должны быть целыми положительными числами. |
n*? n+? n?? n{x}? n{x,}? n{x,y}? | Сопостовление происходит по аналогии с квантификаторами *, +, ? и {...}, однако при этом поиск идет минимально возможного сопоставления. По умолчанию используется "жадный" режим, ? в конце квантификатора позволяет задать "нежадный" режим при котором повторение сопоставления происходит минимально возможное количество раз. |
x(?=y) | Позволяет сопоставить x , только если за x следует y . |
x(?!y) | Позволяет сопоставить x , только если за x не следует y . |
x|y | Сопоставление происходит с любой из указанных альтернатив. |
Группировка и обратные ссылки
Символ | Описание |
---|---|
(x) | Позволяет найти символ x и запомнить результат сопоставления ("захватывающие скобки"). Сопоставленная подстрока может быть вызвана из элементов результирующего массива ..., [n], или из свойств предопределенного объекта RegExp $1 ..., $9. |
(?:x) | Позволяет найти символ x , но не запоминать результат сопоставления ("незахватывающие скобки"). Сопоставленная подстрока не может быть вызвана из элементов результирующего массива ..., [n], или из свойств предопределенного объекта RegExp $1 ..., $9. |
\n | Обратная ссылка на последнюю подстроку, совпадающую с n-ой по счёту в круглых скобках в регулярном выражении (нумерация скобок идет слева направо). n должно быть целым положительным числом. |
Регулярные выражения
Регулярное выражение - это объект, описывающий символьный шаблон. Класс RegExp в JavaScript представляет регулярные выражения, а объекты классов String и RegExp определяют методы, использующие регулярные выражения для выполнения поиска по шаблону и операций поиска в тексте с заменой. Грамматика регулярных выражений в языке JavaScript содержит достаточно полное подмножество синтаксиса регулярных выражений, используемого в языке Perl 5, поэтому, если вы имеете опыт работы с языком Perl, то вы без труда сможете описывать шаблоны в программах на языке JavaScript.
В число особенностей регулярных выражений языка Perl, которые не поддерживаются в ECMAScript, входят флаги s (однострочный режим) и x (расширенный синтаксис); управляющие последовательности \a, \e, \l, \u, \L, \U, \E, \Q, \A, \Z, \z и \G и другие расширенные конструкции, начинающиеся с (?.
Определение регулярных выражений
В JavaScript регулярные выражения представлены объектами RegExp . Объекты RegExp могут быть созданы посредством конструктора RegExp(), но чаще они создаются с помощью специального синтаксиса литералов. Так же как строковые литералы задаются в виде символов, заключенных в кавычки, литералы регулярных выражений задаются в виде символов, заключенных в пару символов слэша (/). Таким образом, JavaScript-код может содержать строки, похожие на эту:
Var pattern = /s$/;
Эта строка создает новый объект RegExp и присваивает его переменной pattern. Данный объект RegExp ищет любые строки, заканчивающиеся символом "s". Это же регулярное выражение может быть определено с помощью конструктора RegExp():
Var pattern = new RegExp("s$");
Спецификация шаблона регулярного выражения состоит из последовательности символов. Большая часть символов, включая все алфавитно-цифровые, буквально описывают символы, которые должны присутствовать. То есть регулярное выражение /java/ совпадает со всеми строками, содержащими подстроку «java».
Другие символы в регулярных выражениях не предназначены для поиска их точных эквивалентов, а имеют особое значение. Например, регулярное выражение /s$/ содержит два символа. Первый символ s обозначает поиск буквального символа. Второй, $ - это специальный метасимвол, обозначающий конец строки. Таким образом, это регулярное выражение соответствует любой строке, заканчивающейся символом s.
В следующих разделах описаны различные символы и метасимволы, используемые в регулярных выражениях в языке JavaScript.
Символы литералов
Как отмечалось ранее, все алфавитные символы и цифры в регулярных выражениях соответствуют сами себе. Синтаксис регулярных выражений в JavaScript также поддерживает возможность указывать некоторые неалфавитные символы с помощью управляющих последовательностей, начинающихся с символа обратного слэша (\). Например, последовательность \n соответствует символу перевода строки. Эти символы перечислены в таблице ниже:
Некоторые знаки препинания имеют в регулярных выражениях особый смысл:
^ $ . * + ? = ! : | \ / () { } -
Значение этих символов раскрывается в последующих разделах. Некоторые из них имеют специальный смысл только в определенных контекстах регулярных выражений, а в других контекстах трактуются буквально. Однако, как правило, чтобы включить какой-либо из этих символов в регулярное выражение буквально, необходимо поместить перед ним символ обратного слэша. Другие символы, такие как кавычки и @, не имеют специального значения и просто соответствуют в регулярных выражениях самим себе.
Если вы не можете точно вспомнить, каким из символов должен предшествовать символ \, можете спокойно помещать обратный слэш перед любым из символов. Однако имейте в виду, что многие буквы и цифры вместе с символом слэша обретают специальное значение, поэтому тем буквам и цифрам, которые вы ищете буквально, не должен предшествовать символ \. Чтобы включить в регулярное выражение сам символ обратного слэша, перед ним, очевидно, следует поместить другой символ обратного слэша. Например, следующее регулярное выражение соответствует любой строке, содержащей символ обратного слэша: /\\/.
Классы символов
Отдельные символы литералов могут объединяться в классы символов путем помещения их в квадратные скобки. Класс символов соответствует любому символу, содержащемуся в этом классе. Следовательно, регулярное выражение // соответствует одному из символов a, b или c.
Могут также определяться классы символов с отрицанием, соответствующие любому символу, кроме тех, которые указаны в скобках. Класс символов с отрицанием задается символом ^ в качестве первого символа, следующего за левой скобкой. Регулярное выражение /[^abc]/ соответствует любому символу, отличному от a, b или c. В классах символов диапазон символов может задаваться при помощи дефиса. Поиск всех символов латинского алфавита в нижнем регистре осуществляется посредством выражения //, а любую букву или цифру из набора символов Latin можно найти при помощи выражения //.
Некоторые классы символов используются особенно часто, поэтому синтаксис регулярных выражений в JavaScript включает специальные символы и управляющие (escape) последовательности для их обозначения. Так, \s соответствует символам пробела, табуляции и любым пробельным символам из набора Unicode, а \S - любым символам, не являющимся пробельными символами из набора Unicode.
В таблице ниже приводится перечень этих спецсимволов и синтаксиса классов символов. (Обратите внимание, что некоторые из управляющих последовательностей классов символов соответствуют только ASCII-символам и не расширены для работы с Unicode-символами. Можно явно определить собственные классы Unicode-символов, например, выражение /[\u0400-\u04FF]/ соответствует любому символу кириллицы.)
Символ | Соответствие |
---|---|
[...] | Любой из символов, указанных в скобках |
[^...] | Любой из символов, не указанных в скобках |
. | Любой символ, кроме перевода строки или другого разделителя Unicode-строки |
\w | Любой текстовый ASCII-символ. Эквивалентно |
\W | Любой символ, не являющийся текстовым ASCII-символом. Эквивалентно [^a-zA-Z0-9_] |
\s | Любой пробельный символ из набора Unicode |
\S | Любой непробельный символ из набора Unicode. Обратите внимание, что символы \w и \S - это не одно и то же |
\d | Любые ASCII-цифры. Эквивалентно |
\D | Любой символ, отличный от ASCII-цифр. Эквивалентно [^0-9] |
[\b] | Литерал символа «забой» |
Обратите внимание, что управляющие последовательности специальных символов классов могут находиться в квадратных скобках. \s соответствует любому пробельному символу, а \d соответствует любой цифре, следовательно, /[\s\d]/ соответствует любому пробельному символу или цифре.
Повторение
Имея знания синтаксиса регулярных выражений, полученные к настоящему моменту, мы можем описать число из двух цифр как /\d\d/ или из четырех цифр как /\d\d\d\d/, но не сможем, например, описать число, состоящее из любого количества цифр, или строку из трех букв, за которыми следует необязательная цифра. Эти более сложные шаблоны используют синтаксис регулярных выражений, указывающий, сколько раз может повторяться данный элемент регулярного выражения.
Символы, обозначающие повторение, всегда следуют за шаблоном, к которому они применяются. Некоторые виды повторений используются довольно часто, и для обозначения этих случаев имеются специальные символы. Например, + соответствует одному или нескольким экземплярам предыдущего шаблона. В следующей таблице приведена сводка синтаксиса повторений:
Следующие строки демонстрируют несколько примеров:
Var pattern = /\d{2,4}/; // Соответствует числу, содержащему от двух до четырех цифр pattern = /\w{3}\d?/; // Соответствует в точности трем символам слова и одной необязательной цифре pattern = /\s+java\s+/; // Соответствует слову "java" с одним или более пробелами // до и после него pattern = /[^(]*/; // Соответствует нулю или более символам, отличным от открывающей круглой скобки
Будьте внимательны при использовании символов повторения * и?. Они могут соответствовать отсутствию указанного перед ними шаблона и, следовательно, отсутствию символов. Например, регулярному выражению /a*/ соответствует строка "bbbb", поскольку в ней нет символа a.
Символы повторения, перечисленные в таблице, соответствуют максимально возможному количеству повторений, при котором обеспечивается поиск последующих частей регулярного выражения. Мы говорим, что это - «жадное» повторение. Имеется также возможность реализовать повторение, выполняемое «нежадным» способом. Достаточно указать после символа (или символов) повторения вопросительный знак: ??, +?, *? или даже {1,5}?.
Например, регулярное выражение /a+/ соответствует одному или более экземплярам буквы a. Примененное к строке «aaa», оно соответствует всем трем буквам. С другой стороны, выражение /a+?/ соответствует одному или более экземплярам буквы a и выбирает наименее возможное число символов. Примененный к той же строке, этот шаблон соответствует только первой букве a.
«Нежадное» повторение не всегда дает ожидаемый результат. Рассмотрим шаблон /a+b/, соответствующий одному или более символам a, за которыми следует символ b. Применительно к строке «aaab» ему соответствует вся строка.
Теперь проверим «нежадную» версию /a+?b/. Можно было бы подумать, что она должна соответствовать символу b, перед которым стоит только один символ a. В случае применения к той же строке «aaab» можно было бы ожидать, что она совпадет с единственным символом a и последним символом b. Однако на самом деле этому шаблону соответствует вся строка, как и в случае «жадной» версии. Дело в том, что поиск по шаблону регулярного выражения выполняется путем нахождения первой позиции в строке, начиная с которой соответствие становится возможным. Так как соответствие возможно, начиная с первого символа строки, более короткие соответствия, начинающиеся с последующих символов, даже не рассматриваются.
Альтернативы, группировка и ссылки
Грамматика регулярных выражений включает специальные символы определения альтернатив, подвыражений группировки и ссылок на предыдущие подвыражения. Символ вертикальной черты | служит для разделения альтернатив. Например, /ab|cd|ef/ соответствует либо строке «ab», либо строке «cd», либо строке «ef», а шаблон /\d{3}|{4}/ - либо трем цифрам, либо четырем строчным буквам.
Обратите внимание, что альтернативы обрабатываются слева направо до тех пор, пока не будет найдено соответствие. При обнаружении совпадения с левой альтернативой правая игнорируется, даже если можно добиться «лучшего» соответствия. Поэтому, когда к строке «ab» применяется шаблон /a|ab/, он будет соответствовать только первому символу.
Круглые скобки имеют в регулярных выражениях несколько значений. Одно из них - группировка отдельных элементов в одно подвыражение, так что элементы при использовании специальных символов |, *, +, ? и других рассматриваются как одно целое. Например, шаблон /java(script)?/ соответствует слову «java», за которым следует необязательное слово «script», а /(ab|cd)+|ef)/ соответствует либо строке «ef», либо одному или более повторений одной из строк «ab» или «cd».
Другим применением скобок в регулярных выражениях является определение подшаблонов внутри шаблона. Когда в целевой строке найдено совпадение с регулярным выражением, можно извлечь часть целевой строки, соответствующую любому конкретному подшаблону, заключенному в скобки.
Предположим, что требуется отыскать одну или более букв в нижнем регистре, за которыми следует одна или несколько цифр. Для этого можно воспользоваться шаблоном /+\d+/. Но предположим также, что нам нужны только цифры в конце каждого соответствия. Если поместить эту часть шаблона в круглые скобки (/+(\d+)/), то можно будет извлечь цифры из любых найденных нами соответствий. Как это делается, будет описано ниже.
С этим связано еще одно применение подвыражений в скобках, позволяющее ссылаться на подвыражения из предыдущей части того же регулярного выражения. Это достигается путем указания одной или нескольких цифр после символа \. Цифры ссылаются на позицию подвыражения в скобках внутри регулярного выражения. Например, \1 ссылается на первое подвыражение, а \3 - на третье. Обратите внимание, что подвыражения могут быть вложены одно в другое, поэтому при подсчете используется позиция левой скобки. Например, в следующем регулярном выражении ссылка на вложенное подвыражение (cript) будет выглядеть как \2:
/(ava(cript)?)\sis\s(fun\w*)/
Ссылка на предыдущее подвыражение указывает не на шаблон этого подвыражения, а на найденный текст, соответствующий этому шаблону. Поэтому ссылки могут использоваться для наложения ограничения, выбирающего части строки, содержащие точно такие же символы. Например, следующее регулярное выражение соответствует нулю или более символам внутри одинарных или двойных кавычек. Однако оно не требует, чтобы открывающие и закрывающие кавычки соответствовали друг другу (т.е. чтобы обе кавычки были одинарными или двойными):
/[""][^""]*[""]/
Соответствия кавычек мы можем потребовать посредством такой ссылки:
Здесь \1 соответствует совпадению с первым подвыражением. В этом примере ссылка налагает ограничение, требующее, чтобы закрывающая кавычка соответствовала открывающей. Это регулярное выражение не допускает присутствия одинарных кавычек внутри двойных, и наоборот.
Возможна также группировка элементов в регулярном выражении без создания нумерованной ссылки на эти элементы. Вместо простой группировки элементов между (и) начните группу с символов (?: и закончите ее символом). Рассмотрим, например, следующий шаблон:
/(ava(?:cript)?)\sis\s(fun\w*)/
Здесь подвыражение (?:cript) необходимо только для группировки, чтобы к группе мог быть применен символ повторения?. Эти модифицированные скобки не создают ссылку, поэтому в данном регулярном выражении \2 ссылается на текст, соответствующий шаблону (fun\w*).
В следующей таблице приводится перечень операторов выбора из альтернатив, группировки и ссылки в регулярных выражениях:
Символ | Значение |
---|---|
| | Альтернатива. Соответствует либо подвыражению слева, либо подвыражению справа. |
(...) | Группировка. Группирует элементы в единое целое, которое может использоваться с символами *, +, ?, | и т.п. Также запоминает символы, соответствующие этой группе для использования в последующих ссылках. |
(?:...) | Только группировка. Группирует элементы в единое целое, но не запоминает символы, соответствующие этой группе. |
\number | Соответствует тем же символам, которые были найдены при сопоставлении с группой с номером number. Группы - это подвыражения внутри скобок (возможно, вложенных). Номера группам присваиваются путем подсчета левых скобок слева направо. Группы, сформированные с помощью символов (?:, не нумеруются. |
Указание позиции соответствия
Как описывалось ранее, многие элементы регулярного выражения соответствуют одному символу в строке. Например, \s соответствует одному пробельному символу. Другие элементы регулярных выражений соответствуют позициям между символами, а не самим символам. Например, \b соответствует границе слова - границе между \w (текстовый ASCII-символ) и \W (нетекстовый символ) или границе между текстовым ASCII-символом и началом или концом строки.
Такие элементы, как \b, не определяют какие-либо символы, которые должны присутствовать в найденной строке, однако они определяют допустимые позиции для проверки соответствия. Иногда эти элементы называются якорными элементами регулярных выражений, потому что они закрепляют шаблон за определенной позицией в строке. Чаще других используются такие якорные элементы, как ^ и $, привязывающие шаблоны соответственно к началу и концу строки.
Например, слово «JavaScript», находящееся на отдельной строке, можно найти с помощью регулярного выражения /^JavaScript$/. Чтобы найти отдельное слово «Java» (а не префикс, например в слове «JavaScript»), можно попробовать применить шаблон /\sJava\s/, который требует наличия пробела до и после слова.
Но такое решение порождает две проблемы. Во-первых, оно найдет слово «Java», только если оно окружено пробелами с обеих сторон, и не сможет найти его в начале или в конце строки. Во-вторых, когда этот шаблон действительно найдет соответствие, возвращаемая им строка будет содержать ведущие и замыкающие пробелы, а это не совсем то, что нам нужно. Поэтому вместо шаблона, совпадающего с пробельными символами \s, мы воспользуемся шаблоном (или якорем), совпадающим с границами слова \b. Получится следующее выражение: /\bJava\b/.
Якорный элемент \B соответствует позиции, не являющейся границей слова. То есть шаблону /\Bcript/ будут соответствовать слова «JavaScript» и «postscript» и не будут соответствовать слова «script» или «Scripting».
В качестве якорных условий могут также выступать произвольные регулярные выражения. Если поместить выражение между символами (?= и), оно превратится в опережающую проверку на совпадение с последующими символами, требующую, чтобы эти символы соответствовали указанному шаблону, но не включались в строку соответствия.
Например, чтобы найти совпадение с названием распространенного языка программирования, за которым следует двоеточие, можно воспользоваться выражением /ava(cript)?(?=\:)/. Этому шаблону соответствует слово «JavaScript» в строке «JavaScript: The Definitive Guide», но ему не будет соответствовать слово «Java» в строке «Java in a Nutshell», потому что за ним не следует двоеточие.
Если же ввести условие (?!, то это будет негативная опережающая проверка на последующие символы, требующая, чтобы следующие символы не соответствовали указанному шаблону. Например, шаблону /Java(?!Script)(\w*)/ соответствует подстрока «Java», за которой следует заглавная буква и любое количество текстовых ASCII-символов при условии, что за подстрокой «Java» не следует подстрока «Script». Он совпадет со строкой «JavaBeans», но не совпадет со строкой «Javanese», совпадет со строкой «JavaScrip», но не совпадет со строками «JavaScript» или «JavaScripter».
В таблице ниже приводится перечень якорных символов регулярных выражений:
Символ | Значение |
---|---|
^ | Соответствует началу строкового выражения или началу строки при многострочном поиске. |
$ | Соответствует концу строкового выражения или концу строки при многострочном поиске. |
\b | Соответствует границе слова, т.е. соответствует позиции между символом \w и символом \W или между символом \w и началом или концом строки. (Однако обратите внимание, что [\b] соответствует символу забоя.) |
\B | Соответствует позиции, не являющейся границей слов. |
(?=p) | Позитивная опережающая проверка на последующие символы. Требует, чтобы последующие символы соответствовали шаблону p, но не включает эти символы в найденную строку. |
(?!p) | Негативная опережающая проверка на последующие символы. Требует, чтобы следующие символы не соответствовали шаблону p. |
Флаги
И еще один, последний элемент грамматики регулярных выражений. Флаги регулярных выражений задают высокоуровневые правила соответствия шаблонам. В отличие от остальной грамматики регулярных выражений, флаги указываются не между символами слэша, а после второго из них. В языке JavaScript поддерживается три флага.
Флаг i указывает, что поиск по шаблону должен быть нечувствителен к регистру символов, а флаг g - что поиск должен быть глобальным, т.е. должны быть найдены все соответствия в строке. Флаг m выполняет поиск по шаблону в многострочном режиме. Если строковое выражение, в котором выполняется поиск, содержит символы перевода строк, то в этом режиме якорные символы ^ и $, помимо того, что они соответствуют началу и концу всего строкового выражения, также соответствуют началу и концу каждой текстовой строки. Например, шаблону /java$/im соответствует как слово «java», так и «Java\nis fun».
Эти флаги могут объединяться в любые комбинации. Например, чтобы выполнить поиск первого вхождения слова «java» (или «Java», «JAVA» и т.д.) без учета регистра символов, можно воспользоваться нечувствительным к регистру регулярным выражением /\bjava\b/i. А чтобы найти все вхождения этого слова в строке, можно добавить флаг g: /\bjava\b/gi.
Методы класса String для поиска по шаблону
До этого момента мы обсуждали грамматику создаваемых регулярных выражений, но не рассматривали, как эти регулярные выражения могут фактически использоваться в JavaScript-сценариях. В данном разделе мы обсудим методы объекта String, в которых регулярные выражения применяются для поиска по шаблону, а также для поиска с заменой. А затем продолжим разговор о поиске по шаблону с регулярными выражениями, рассмотрев объект RegExp, его методы и свойства.
Строки поддерживают четыре метода, использующие регулярные выражения. Простейший из них - метод search() . Он принимает в качестве аргумента регулярное выражение и возвращает либо позицию первого символа найденной подстроки, либо -1, если соответствие не найдено. Например, следующий вызов вернет 4:
Var result = "JavaScript".search(/script/i); // 4
Если аргумент метода search() не является регулярным выражением, он сначала преобразуется путем передачи конструктору RegExp. Метод search() не поддерживает глобальный поиск и игнорирует флаг g в своем аргументе.
Метод replace() выполняет операцию поиска с заменой. Он принимает в качестве первого аргумента регулярное выражение, а в качестве второго - строку замены. Метод отыскивает в строке, для которой он вызван, соответствие указанному шаблону.
Если регулярное выражение содержит флаг g, метод replace() заменяет все найденные совпадения строкой замены. В противном случае он заменяет только первое найденное совпадение. Если первый аргумент метода replace() является строкой, а не регулярным выражением, то метод выполняет буквальный поиск строки, а не преобразует его в регулярное выражение с помощью конструктора RegExp(), как это делает метод search().
В качестве примера мы можем воспользоваться методом replace() для единообразной расстановки прописных букв в слове «JavaScript» для всей строки текста:
// Независимо от регистра символов заменяем словом в нужном регистре var result = "javascript".replace(/JavaScript/ig, "JavaScript");
Метод replace() представляет собой более мощное средство, чем можно было бы предположить по этому примеру. Напомню, что подвыражения в скобках, находящиеся внутри регулярного выражения, нумеруются слева направо, и что регулярное выражение запоминает текст, соответствующий каждому из подвыражений. Если в строке замены присутствует знак $ с цифрой, метод replace() заменяет эти два символа текстом, соответствующим указанному подвыражению. Это очень полезная возможность. Мы можем использовать ее, например, для замены прямых кавычек в строке типографскими кавычками, которые имитируются ASCII-символами:
// Цитата - это кавычка, за которой следует любое число символов, // отличных от кавычек (их мы запоминаем), за этими символами // следует еще одна кавычка var quote = /"([^"]*)"/g; // Заменяем прямые кавычки типографскими и оставляем без изменений «$1» // содержимое цитаты, хранящееся в $1 var text = ""JavaScript" - интерпретируемый язык программирования."; var result = text.replace(quote, "«$1»"); // «JavaScript» - интерпретируемый язык программирования.
Важное, что следует отметить, - второй аргумент replace() может быть функцией, динамически вычисляющей строку замены.
Метод match() - это наиболее общий из методов класса String, использующих регулярные выражения. Он принимает в качестве единственного аргумента регулярное выражение (или преобразует свой аргумент в регулярное выражение, передав его конструктору RegExp()) и возвращает массив, содержащий результаты поиска. Если в регулярном выражении установлен флаг g, метод возвращает массив всех соответствий, присутствующих в строке. Например:
// вернет ["1", "2", "3"] var result = "1 плюс 2 равно 3".match(/\d+/g);
Если регулярное выражение не содержит флаг g, метод match() не выполняет глобальный поиск; он просто ищет первое совпадение. Однако match() возвращает массив, даже когда метод не выполняет глобальный поиск. В этом случае первый элемент массива - это найденная подстрока, а все оставшиеся элементы представляют собой подвыражения регулярного выражения. Поэтому если match() возвращает массив arr, то arr будет содержать найденную строку целиком, arr -подстроку, соответствующую первому подвыражению, и т.д. Проводя параллель с методом replace(), можно сказать, что в arr[n] заносится содержимое $n.
Например, взгляните на следующий программный код, выполняющий разбор URL-адреса:
Var url = /(\w+):\/\/([\w.]+)\/(\S*)/; var text = "Посетите наш сайт http://www..php"; var result = text.match(url); if (result != null) { var fullurl = result; // Содержит "http://www..php" var protocol = result; // Содержит "http" var host = result; // Содержит "www..php" }
Следует отметить, что для регулярного выражения, в котором не установлен флаг g глобального поиска, метод match() возвращает то же значение, что и метод exec() регулярного выражения: возвращаемый массив имеет свойства index и input, как описывается в обсуждении метода exec() ниже.
Последний из методов объекта String, в котором используются регулярные выражения - split() . Этот метод разбивает строку, для которой он вызван, на массив подстрок, используя аргумент в качестве разделителя. Например:
"123,456,789".split(","); // Вернет ["123","456","789"]
Метод split() может также принимать в качестве аргумента регулярное выражение. Это делает метод более мощным. Например, можно указать разделитель, допускающий произвольное число пробельных символов с обеих сторон:
"1, 2, 3 , 4 , 5".split(/\s*,\s*/); // Вернет ["1","2","3","4","5"]
Объект RegExp
Как было упомянуто, регулярные выражения представлены в виде объектов RegExp. Помимо конструктора RegExp(), объекты RegExp поддерживают три метода и несколько свойств.
Конструктор RegExp() принимает один или два строковых аргумента и создает новый объект RegExp. Первый аргумент конструктора - это строка, содержащая тело регулярного выражения, т.е. текст, который должен находиться между символами слэша в литерале регулярного выражения. Обратите внимание, что в строковых литералах и регулярных выражениях для обозначения управляющих последовательностей используется символ \, поэтому, передавая конструктору RegExp() регулярное выражение в виде строкового литерала, необходимо заменить каждый символ \ парой символов \\.
Второй аргумент RegExp() может отсутствовать. Если он указан, то определяет флаги регулярного выражения. Это должен быть один из символов g, i, m либо комбинация этих символов. Например:
// Находит все пятизначные числа в строке. Обратите внимание // на использование в этом примере символов \\ var zipcode = new RegExp("\\d{5}", "g");
Конструктор RegExp() удобно использовать, когда регулярное выражение создается динамически и поэтому не может быть представлено с помощью синтаксиса литералов регулярных выражений. Например, чтобы найти строку, введенную пользователем, надо создать регулярное выражение во время выполнения с помощью RegExp().
Свойства RegExp
Каждый объект RegExp имеет пять свойств. Свойство source - строка, доступная только для чтения, содержащая текст регулярного выражения. Свойство global - логическое значение, доступное только для чтения, определяющее наличие флага g в регулярном выражении. Свойство ignoreCase - это логическое значение, доступное только для чтения, определяющее наличие флага i в регулярном выражении. Свойство multiline - это логическое значение, доступное только для чтения, определяющее наличие флага m в регулярном выражении. И последнее свойство lastIndex - это целое число, доступное для чтения и записи. Для шаблонов с флагом g это свойство содержит номер позиции в строке, с которой должен быть начат следующий поиск. Как описано ниже, оно используется методами exec() и test().
Методы RegExp
Объекты RegExp определяют два метода, выполняющие поиск по шаблону; они ведут себя аналогично методам класса String, описанным выше. Основной метод класса RegExp, используемый для поиска по шаблону - exec() . Он похож на упоминавшийся метод match() класса String, за исключением того, что является методом класса RegExp, принимающим в качестве аргумента строку, а не методом класса String, принимающим аргумент RegExp.
Метод exec() выполняет регулярное выражение для указанной строки, т.е. ищет совпадение в строке. Если совпадение не найдено, метод возвращает null. Однако если соответствие найдено, он возвращает такой же массив, как массив, возвращаемый методом match() для поиска без флага g. Нулевой элемент массива содержит строку, соответствующую регулярному выражению, а все последующие элементы - подстроки, соответствующие всем подвыражениям. Кроме того, свойство index содержит номер позиции символа, которым начинается соответствующий фрагмент, а свойство input ссылается на строку, в которой выполнялся поиск.
В отличие от match(), метод exec() возвращает массив, структура которого не зависит от наличия в регулярном выражении флага g. Напомню, что при передаче глобального регулярного выражения метод match() возвращает массив найденных соответствий. А exec() всегда возвращает одно соответствие, но предоставляет о нем полную информацию. Когда exec() вызывается для регулярного выражения, содержащего флаг g, метод устанавливает свойство lastIndex объекта регулярного выражения равным номеру позиции символа, следующего непосредственно за найденной подстрокой.
Когда метод exec() вызывается для того же регулярного выражения второй раз, он начинает поиск с символа, позиция которого указана в свойстве lastIndex. Если exec() не находит соответствия, свойство lastIndex получает значение 0. (Вы также можете установить lastIndex в ноль в любой момент, что следует делать во всех тех случаях, когда поиск завершается до того, как будет найдено последнее соответствие в одной строке, и начинается поиск в другой строке с тем же объектом RegExp.) Это особое поведение позволяет вызывать exec() повторно для перебора всех соответствий регулярному выражению в строке. Например:
Var pattern = /Java/g; var text = "JavaScript - это более забавная штука, чем Java!"; var result; while((result = pattern.exec(text)) != null) { console.log("Найдено "" + result + """ + " в позиции " + result.index + "; следующий поиск начнется с " + pattern.lastIndex); }
Еще один метод объекта RegExp - test() , который намного проще метода exec(). Он принимает строку и возвращает true, если строка соответствует регулярному выражению:
Var pattern = /java/i; pattern.test("JavaScript"); // Вернет true
Вызов test() эквивалентен вызову exec(), возвращающему true, если exec() возвращает не null. По этой причине метод test() ведет себя так же, как метод exec() при вызове для глобального регулярного выражения: он начинает искать указанную строку с позиции, заданной свойством lastIndex, и если находит соответствие, устанавливает свойство lastIndex равным номеру позиции символа, непосредственно следующего за найденным соответствием. Поэтому с помощью метода test() можно так же сформировать цикл обхода строки, как с помощью метода exec().