Регулярные выражения
Содержание:
Введение в регулярные выражения
Язык регулярных выражений предназначен специально для обработки строк. Он включает два средства:
-
Набор управляющих кодов для идентификации специфических типов символов
-
Система для группирования частей подстрок и промежуточных результатов таких действий
С помощью регулярных выражений можно выполнять достаточно сложные и высокоуровневые действия над строками:
-
Идентифицировать (и возможно, помечать к удалению) все повторяющиеся слова в строке
-
Сделать заглавными первые буквы всех слов
-
Преобразовать первые буквы всех слов длиннее трех символов в заглавные
-
Обеспечить правильную капитализацию предложений
-
Выделить различные элементы в URI (например, имея http://www.professorweb.ru, выделить протокол, имя компьютера, имя файла и т.д.)
Главным преимуществом регулярных выражений является использование метасимволов — специальные символы, задающие команды, а также управляющие последовательности, которые работают подобно управляющим последовательностям C#. Это символы, предваренные знаком обратного слеша (\) и имеющие специальное назначение.
В следующей таблице специальные метасимволы регулярных выражений C# сгруппированы по смыслу:
Метасимволы, используемые в регулярных выражениях C#
Символ
Значение
Пример
Соответствует
Классы символов
Любой из символов, указанных в скобках
В исходной строке может быть любой символ английского алфавита в нижнем регистре
Любой из символов, не указанных в скобках
В исходной строке может быть любой символ кроме цифр
.
Любой символ, кроме перевода строки или другого разделителя Unicode-строки
\w
Любой текстовый символ, не являющийся пробелом, символом табуляции и т.п.
\W
Любой символ, не являющийся текстовым символом
\s
Любой пробельный символ из набора Unicode
\S
Любой непробельный символ из набора Unicode
Обратите внимание, что символы \w и \S — это не одно и то же
\d
Любые ASCII-цифры. Эквивалентно
\D
Любой символ, отличный от ASCII-цифр
Эквивалентно
Символы повторения
{n,m}
Соответствует предшествующему шаблону, повторенному не менее n и не более m раз
s{2,4}
«Press», «ssl», «progressss»
{n,}
Соответствует предшествующему шаблону, повторенному n или более раз
s{1,}
«ssl»
{n}
Соответствует в точности n экземплярам предшествующего шаблона
s{2}
«Press», «ssl», но не «progressss»
?
Соответствует нулю или одному экземпляру предшествующего шаблона; предшествующий шаблон является необязательным
Эквивалентно {0,1}
+
Соответствует одному или более экземплярам предшествующего шаблона
Эквивалентно {1,}
*
Соответствует нулю или более экземплярам предшествующего шаблона
Эквивалентно {0,}
Символы регулярных выражений выбора
|
Соответствует либо подвыражению слева, либо подвыражению справа (аналог логической операции ИЛИ).
(…)
Группировка. Группирует элементы в единое целое, которое может использоваться с символами *, +, ?, | и т.п. Также запоминает символы, соответствующие этой группе для использования в последующих ссылках.
(?:…)
Только группировка. Группирует элементы в единое целое, но не запоминает символы, соответствующие этой группе.
Якорные символы регулярных выражений
^
Соответствует началу строкового выражения или началу строки при многострочном поиске.
^Hello
«Hello, world», но не «Ok, Hello world» т.к. в этой строке слово «Hello» находится не в начале
$
Соответствует концу строкового выражения или концу строки при многострочном поиске.
Hello$
«World, Hello»
\b
Соответствует границе слова, т.е. соответствует позиции между символом \w и символом \W или между символом \w и началом или концом строки.
\b(my)\b
В строке «Hello my world» выберет слово «my»
\B
Соответствует позиции, не являющейся границей слов.
\B(ld)\b
Соответствие найдется в слове «World», но не в слове «ld»
Скобочные группы ― ()
a(bc) создаём группу со значением bc -> тестa(?:bc)* оперетор ?: отключает группу -> тестa(?<foo>bc) так, мы можем присвоить имя группе -> тест
Этот оператор очень полезен, когда нужно извлечь информацию из строк или данных, используя ваш любимый язык программирования. Любые множественные совпадения, по нескольким группам, будут представлены в виде классического массива: доступ к их значениям можно получить с помощью индекса из результатов сопоставления.
Если присвоить группам имена (используя ), то можно получить их значения, используя результат сопоставления, как словарь, где ключами будут имена каждой группы.
Metacharacters
Metacharacters are characters with a special meaning:
Metacharacter | Description |
---|---|
. | Find a single character, except newline or line terminator |
\w | Find a word character |
\W | Find a non-word character |
\d | Find a digit |
\D | Find a non-digit character |
\s | Find a whitespace character |
\S | Find a non-whitespace character |
\b | Find a match at the beginning/end of a word, beginning like this: \bHI, end like this: HI\b |
\B | Find a match, but not at the beginning/end of a word |
\0 | Find a NULL character |
\n | Find a new line character |
\f | Find a form feed character |
\r | Find a carriage return character |
\t | Find a tab character |
\v | Find a vertical tab character |
\xxx | Find the character specified by an octal number xxx |
\xdd | Find the character specified by a hexadecimal number dd |
\udddd | Find the Unicode character specified by a hexadecimal number dddd |
Найти все / Заменить все
Эти две задачи решаются в javascript принципиально по-разному.
Начнем с «простого».
Для замены всех вхождений используется метод String#replace.
Он интересен тем, что допускает первый аргумент — регэксп или строку.
Если первый аргумент — строка, то будет осуществлен поиск подстроки, без преобразования в регулярное выражение.
Попробуйте:
alert("2 ++ 1".replace("+", "*"))
Каков результат? Как, заменился только один плюс, а не два? Да, вот так.
В режиме регулярного выражения плюс придется заэкранировать, но зато заменит все вхождения (при указании флага ):
alert("2 ++ 1".replace(/\+/g, "*"))
Вот такая особенность работы со строкой.
Очень полезной особенностью является возможность работать с функцией вместо строки замены. Такая функция получает первым аргументом — все совпадение, а последующими аргументами — скобочные группы.
Следующий пример произведет операции вычитания:
var str = "count 36 - 26, 18 - 9" str = str.replace(/(\d+) - (\d+)/g, function(a,b,c) { return b-c }) alert(str)
В javascript нет одного универсального метода для поиска всех совпадений.
Для поиска без запоминания скобочных групп — можно использовать String#match:
var str = "count 36-26, 18-9" var re = /(\d+)-(\d+)/g result = str.match(re) for(var i=0; i<result.length; i++) alert(result)
Как видите, оно исправно ищет все совпадения (флаг у регулярного выражения обязателен), но при этом не запоминает скобочные группы. Эдакий «облегченный вариант».
В сколько-нибудь сложных задачах важны не только совпадения, но и скобочные группы. Чтобы их найти, предлагается использовать многократный вызов RegExp#exec.
Для этого регулярное выражение должно использовать флаг . Тогда результат поиска, запомненный в свойстве объекта используется как точка отсчета для следующего поиска:
var str = "count 36-26, 18-9" var re = /(\d+)-(\d+)/g var res while ( (res = re.exec(str)) != null) { alert("Найдено " + res + ": ("+ res+") и ("+res+")") alert("Дальше ищу с позиции "+re.lastIndex) }
Проверка нужна т.к. значение является хорошим и означает, что вхождение найдено в самом начале строки (поиск успешен). Поэтому необходимо сравнивать именно с .
Строковые методы, поиск и замена
Следующие методы работают с регулярными выражениями из строк.
Все методы, кроме 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); }
Статичные регэкспы
В некоторых реализациях javascript регэкспы, заданные коротким синтаксисом /…/ — статичны. То есть, такой объект создается один раз в некоторых реализациях JS, например в Firefox. В Chrome все ок.
function f() { // при многократных заходах в функцию объект один и тот же var re = /lalala/ }
По стандарту эта возможность разрешена ES3, но запрещена ES5.
Из-за того, что при глобальном поиске меняется, а сам объект регэкспа статичен, первый поиск увеличивает , а последующие — продолжают искать со старого , т.е. могут возвращать не все результаты.
При поиске всех совпадений в цикле проблем не возникает, т.к. последняя итерация (неудачная) обнуляет .
Примеры
Разберём скобки на примерах.
Без скобок шаблон означает символ и идущий после него символ , который повторяется один или более раз. Например, или .
Скобки группируют символы вместе. Так что означает , , и т.п.
Сделаем что-то более сложное – регулярное выражение, которое соответствует домену сайта.
Например:
Как видно, домен состоит из повторяющихся слов, причём после каждого, кроме последнего, стоит точка.
На языке регулярных выражений :
Поиск работает, но такому шаблону не соответствует домен с дефисом, например, , так как дефис не входит в класс .
Можно исправить это, заменим на везде, кроме как в конце: .
Итоговый шаблон:
Квантификаторы
Квантификаторы используются, когда необходимо указать количество символов или выражений, по которым производится сопоставление.
/* Квантификатор - Значение */* - 0 или более совпадений с предшествующим выражением.+ - 1 или более совпадений с предшествующим выражением.? - Предшествующее выражение необязательно (то есть совпадений 0 или 1).x{n} - "n" должно быть целым положительным числом. Количество вхождений предшествующего выражения "x" равно "n".x{n, } - "n" должно быть целым положительным числом. Количество вхождений предшествующего выражения "x" равно, как минимум, "n".x{n, m} - "n" может быть равно 0 или целому положительному числу. "m" - целое положительное число. Если "m" > "n", количество вхождений предшествующего выражения "x" равно минимум "n" и максимум "m".
Примеры:
// * - 0 или более совпадений с предшествующим выражениемconst myPattern = /bo*k/console.log(myPattern.test('b'))// falseconsole.log(myPattern.test('bk'))// trueconsole.log(myPattern.test('bok'))// true// + - 1 или более совпадений с предшествующим выражениемconst myPattern = /\d+/console.log(myPattern.test('word'))// falseconsole.log(myPattern.test(13))// true// ? - Предшествующее выражение необязательно, совпадений 0 или 1const myPattern = /foo?bar/console.log(myPattern.test('foobar'))// trueconsole.log(myPattern.test('fooobar'))// false// x{n} - Количество вхождений предшествующего выражения "x" равно "n"const myPattern = /bo{2}m/console.log(myPattern.test('bom'))// falseconsole.log(myPattern.test('boom'))// trueconsole.log(myPattern.test('booom'))// false// x{n, } - Количество вхождений предшествующего выражения "x" равно, как минимум, "n"const myPattern = /do{2,}r/console.log(myPattern.test('dor'))// falseconsole.log(myPattern.test('door'))// trueconsole.log(myPattern.test('dooor'))// true// x{n, m} - Количество вхождений предшествующего выражения "x" равно минимум "n" и максимум "m"const myPattern = /zo{1,3}m/console.log(myPattern.test('zom'))// falseconsole.log(myPattern.test('zoom'))// trueconsole.log(myPattern.test('zooom'))// trueconsole.log(myPattern.test('zoooom'))// false
Содержимое скобок в match
Скобочные группы нумеруются слева направо. Поисковый движок запоминает содержимое, которое соответствует каждой скобочной группе, и позволяет получить его в результате.
Метод , если у регулярного выражения нет флага , ищет первое совпадение и возвращает его в виде массива:
- На позиции будет всё совпадение целиком.
- На позиции – содержимое первой скобочной группы.
- На позиции – содержимое второй скобочной группы.
- …и так далее…
Например, мы хотим найти HTML теги и обработать их. Было бы удобно иметь содержимое тега (то, что внутри уголков) в отдельной переменной.
Давайте заключим внутреннее содержимое в круглые скобки: .
Теперь получим как тег целиком , так и его содержимое в виде массива:
Скобки могут быть и вложенными.
Например, при поиске тега в нас может интересовать:
- Содержимое тега целиком: .
- Название тега: .
- Атрибуты тега: .
Заключим их в скобки в шаблоне: .
Вот их номера (слева направо, по открывающей скобке):
В действии:
По нулевому индексу в всегда идёт полное совпадение.
Затем следуют группы, нумеруемые слева направо, по открывающим скобкам. Группа, открывающая скобка которой идёт первой, получает первый индекс в результате – . Там находится всё содержимое тега.
Затем в идёт группа, образованная второй открывающей скобкой – имя тега, далее в будет остальное содержимое тега: .
Соответствие для каждой группы в строке:
Даже если скобочная группа необязательна (например, стоит квантификатор ), соответствующий элемент массива существует и равен .
Например, рассмотрим регулярное выражение . Оно ищет букву , за которой идёт необязательная буква , за которой, в свою очередь, идёт необязательная буква .
Если применить его к строке из одной буквы , то результат будет такой:
Массив имеет длину , но все скобочные группы пустые.
А теперь более сложная ситуация для строки :
Длина массива всегда равна . Для группы ничего нет, поэтому результат: .
Количество {n}
Самый простой квантификатор — это число в фигурных скобках: .
Он добавляется к символу (или символьному классу, или набору и т.д.) и указывает, сколько их нам нужно.
Можно по-разному указать количество, например:
- Точное количество:
-
Шаблон обозначает ровно 5 цифр, он эквивалентен .
Следующий пример находит пятизначное число:
Мы можем добавить , чтобы исключить числа длиннее: .
- Диапазон: , от 3 до 5
-
Для того, чтобы найти числа от 3 до 5 цифр, мы можем указать границы в фигурных скобках:
Верхнюю границу можно не указывать.
Тогда шаблон найдёт последовательность чисел длиной и более цифр:
Давайте вернёмся к строке .
Число – это последовательность из одной или более цифр. Поэтому шаблон будет :
Запрет возврата
Переписывать регулярное выражение не всегда удобно, и не всегда очевидно, как это сделать.
Альтернативный подход заключается в том, чтобы запретить возврат для квантификатора.
Движок регулярных выражений проверяет множество вариантов, которые для человека являются очевидно ошибочными.
Например, в шаблоне для человека очевидно, что в не нужно «откатывать» . От того, что вместо одного у нас будет два независимых , ничего не изменится:
Если говорить об изначальном примере , то хорошо бы исключить возврат для . То есть, для нужно искать только одно слово целиком, максимально возможной длины. Не нужно уменьшать количество повторений , пробовать разбить слово на два , и т.п.
В современных регулярных выражениях для решения этой проблемы придумали захватывающие (possessive) квантификаторы, которые такие же как жадные, но не делают возврат (то есть, по сути, они даже проще, чем жадные).
Также есть «атомарные скобочные группы» – средство, запрещающее возврат внутри скобок.
К сожалению, в JavaScript они не поддерживаются, но есть другое средство.
Мы можем исключить возврат с помощью опережающей проверки.
Шаблон, захватывающий максимальное количество повторений без возврата, выглядит так: .
Расшифруем его:
- Опережающая проверка ищет максимальное количество , доступных с текущей позиции.
- Содержимое скобок вокруг не запоминается движком, поэтому оборачиваем внутри в дополнительные скобки, чтобы движок регулярных выражений запомнил их содержимое.
- …И чтобы далее в шаблоне на него сослаться обратной ссылкой .
То есть, мы смотрим вперед – и если там есть слово , то ищем его же .
Зачем? Всё дело в том, что опережающая проверка находит слово целиком, и мы захватываем его в шаблон посредством . Поэтому мы реализовали, по сути, захватывающий квантификатор . Такой шаблон захватывает только полностью слово , не его часть.
Например, в слове он не может захватить только , и оставить для совпадения с остатком шаблона.
Вот, посмотрите, сравнение двух шаблонов:
- В первом варианте сначала забирает слово целиком, потом постепенно отступает, чтобы попробовать найти оставшуюся часть шаблона, и в конце концов находит (при этом будет соответствовать ).
- Во втором варианте осуществляет опережающую проверку и видит сразу слово , которое целиком захватывает в совпадение, так что уже нет возможности найти .
Внутрь можно вместо вставить и более сложное регулярное выражение, при поиске которого квантификатор не должен делать возврат.
Больше о связи захватывающих квантификаторов и опережающей проверки вы можете найти в статьях Regex: Emulate Atomic Grouping (and Possessive Quantifiers) with LookAhead и Mimicking Atomic Groups.
Перепишем исходный пример, используя опережающую проверку для запрета возврата:
Здесь внутри скобок стоит вместо , так как есть ещё внешние скобки. Чтобы избежать путаницы с номерами скобок, можно дать скобкам имя, например .
Проблему, которой была посвящена эта глава, называют «катастрофический возврат» (catastrophic backtracking).
Мы разобрали два способа её решения:
- Уменьшение возможных комбинаций переписыванием шаблона.
- Запрет возврата.
Строковые методы, поиск и замена
Следующие методы работают с регулярными выражениями из строк.
Все методы, кроме 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); }
Конструктор регулярных выражений
Первый способ — использование конструктора. Это громкое слово на самом деле означает функцию-конструктор объекта RegExp. Конструктор принимает два параметра. Первый — шаблон, который вы хотите описать. Это обязательный параметр. В конце концов, зачем вообще создавать регулярное выражение, если нет шаблона?
Второй параметр — строка с флагами (). Не волнуйтесь, скоро мы с ними познакомимся. Этот параметр необязательный. Стоит запомнить одно: после создания регулярного выражения флаги уже нельзя будет добавить или убрать. Поэтому, если хотите использовать флаг, добавьте его на этапе создания выражения.
// Синтаксис конструктора регулярных выраженийnew RegExp(pattern)// Создание регулярного выражения// с помощью конструктора// без флаговconst myPattern = new RegExp('')// Создание регулярного выражения// с помощью конструктора// с одним флагомconst myPattern = new RegExp('', 'g')
Выводы, рецепты
Будет намного проще понять методы JavaScript RegExp, если мы разделим их по использованию на практике.
Чтобы найти только первое совпадение:
- Найти позицию первого совпадения – str.search(reg);
- Найти полное совпадение – str.match(reg);
- Проверить, есть ли совпадение – regexp.test(str);
- Найти совпадение с заданной позиции – regexp.exec(str), установите regexp.lastIndex в номер позиции.
Чтобы найти все совпадения:
- Массив совпадений – str.match(reg), регулярное выражение с флагом g;
- Получить все совпадения с полной информацией о каждом из них – regexp.exec(str) с флагом g в цикле.
Чтобы найти и заменить:
Заменить одну строку на другую или результат работы функции – str.replace(reg, str|func).
Чтобы разделить строку:
str.split(str|reg).
Кроме этого мы изучили два флага JavaScript RegExp:
- Флаг g — чтобы найти все совпадения (глобальный поиск);
- Флаг y — чтобы искать на точно заданной позиции внутри текста.
Теперь мы знаем методы и можем использовать регулярные выражения.