Javascript регулярные выражения
Содержание:
- Методы Javascript для работы с регулярными выражениями
- Экранирование внутри […]
- Строковые методы, поиск и замена
- Полезные методы работы с регулярными выражениями в JavaScript
- Примеры
- Алгоритм[править]
- Пример
- Точка и перенос строки
- Удаляем заглавные буквы с помощью строк и регулярных выражений
- Backreferences в паттерне и при замене
- Metacharacters
- Quantifiers
- test()
- Создаем собственные регулярные выражения JavaScript
- Содержимое скобок в match
- Назад к словам и строкам
- Указание количества повторений символов в тексте
- МетаСимволы
- Итого
Методы 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(/-/)); //
Экранирование внутри […]
Обычно, когда мы хотим найти специальный символ, нам нужно экранировать его, например . А если нам нужна обратная косая черта, тогда используем , т.п.
В квадратных скобках большинство специальных символов можно использовать без экранирования:
- Символы не нужно экранировать никогда.
- Тире не надо экранировать в начале или в конце (где оно не задаёт диапазон).
- Символ каретки нужно экранировать только в начале (где он означает исключение).
- Закрывающую квадратную скобку , если нужен именно такой символ, экранировать нужно.
Другими словами, разрешены без экранирования все специальные символы, кроме случаев, когда они означают что-то особое в наборах.
Точка внутри квадратных скобок – просто точка. Шаблон будет искать один из символов: точку или запятую.
В приведённом ниже примере регулярное выражение ищет один из символов :
…Впрочем, если вы решите экранировать «на всякий случай», то не будет никакого вреда:
Строковые методы, поиск и замена
Следующие методы работают с регулярными выражениями из строк.
Все методы, кроме 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
Регулярные выражения, создаваемые с использованием флагов и последовательностей символов, которые мы обсуждали ранее в этой статье, предназначены для использования с различными методами JavaScript для поиска, замены или разделения строк.
Вот некоторые методы, связанные с регулярными выражениями.
► test() – проверяет, содержит ли основная строка подстроку, которая соответствует шаблону, заданному данным регулярным выражением. При успешном совпадении метод возвращает true, в противном случае — false.
JavaScript
var textA = 'I like APPles very much'; var textB = 'I like APPles'; var regexOne = /apples$/i // вернет false console.log(regexOne.test(textA)); // вернет true console.log(regexOne.test(textB));
В приведённом выше примере приведено регулярное выражение, предназначенное для поиска слова “apples” в случае, если оно расположено в конце строки. Поэтому в первом случае метод вернет false.
► search() – проверяет, содержит ли основная строка подстроку, которая соответствует шаблону, заданному данным регулярным выражением. Метод возвращает индекс совпадения при успехе и -1 в противном случае.
JavaScript
var textA = 'I like APPles very much'; var regexOne = /apples/; var regexTwo = /apples/i; // Результат: -1 console.log(textA.search(regexOne)); // Результат: 7 console.log(textA.search(regexTwo));
В данном примере проверка по превому регулярному выражению вернет -1, потому что не указан флаг нечувствительности к регистру.
► match() – осуществляет поиск подстроки в основной строке. Подстрока должна соответствовать шаблону, заданному данным регулярным выражением. Если используется флаг g, то несколько совпадений будут возвращены в виде массива.
JavaScript
var textA = 'All I see here are apples, APPles and apPleS'; var regexOne = /apples/gi; // Результат: console.log(textA.match(regexOne));
► exec() – производит поиск подстроки в основной строке. В случае, если подстрока соответствует шаблону, заданному данным регулярным выражением, возвращает массив с результатами или null. В свойстве input хранится оригинальная строка
JavaScript
var textA = 'Do you like apples?'; var regexOne = /apples/; // Результат: apples console.log(regexOne.exec(textA)); // Результат : Do you like apples? console.log(regexOne.exec(textA).input);
► replace() – ищет подстроку, соответствующую заданному шаблону и заменяет ее на предоставленную заменяющую строку.
JavaScript
var textA = 'Do you like aPPles?'; var regexOne = /apples/i // Результат: Do you like mangoes? console.log(textA.replace(regexOne, 'mangoes'));
► split() – Этот метод позволит вам разбить основную строку на подстроки на основе разделителя, представленного в виде регулярного выражения.
JavaScript
var textA = 'This 593 string will be brok294en at places where d1gits are.'; var regexOne = /\d+/g // Результат : console.log(textA.split(regexOne))
Примеры
Разберём скобки на примерах.
Без скобок шаблон означает символ и идущий после него символ , который повторяется один или более раз. Например, или .
Скобки группируют символы вместе. Так что означает , , и т.п.
Сделаем что-то более сложное – регулярное выражение, которое соответствует домену сайта.
Например:
Как видно, домен состоит из повторяющихся слов, причём после каждого, кроме последнего, стоит точка.
На языке регулярных выражений :
Поиск работает, но такому шаблону не соответствует домен с дефисом, например, , так как дефис не входит в класс .
Можно исправить это, заменим на везде, кроме как в конце: .
Итоговый шаблон:
Алгоритм[править]
Данный алгоритм работает быстрее недетерминированного конечного автомата, построенного по теореме Клини, но только для регулярных выражений, состоящих из символов:
- — один любой буквенный символ,
- — один любой символ,
- — символ начала текста,
- — символ конца текста,
- — предыдущий символ встречается ноль или более раз.
Например, для , очевидно, проще написать простой сопоставитель, чем строить НКА.
Псевдокодправить
function match(regexp: String, text: String): boolean if regexp == '^' return matchHere(regexp, text) int i = 0 while i text.length if matchHere(regexp, text) return true i++ return false
Функция проверяет есть ли вхождение регулярного выражения в любом месте в пределах текста. Если существует более одного вхождения, то найдется самое левое и самое короткое.
Логика функции проста. Если — первый символ регулярного выражения, то любое возможное вхождение должно начинаться в начале текста. То есть если — регулярное выражение, то должно входить в текст только с первой позиции текста, а не где-то в середине текста. Это проверяется путем сопоставления остатка регулярного выражения с текстом, начиная с первой позиции и нигде более.
В противном случае регулярное выражение может входить в текст в любой позиции. Это проверяется путем сопоставления регулярного выражения во всех позициях текста. Если регулярное выражение входит более одного раза в текст, то только самое левое вхождение будет распознано. То есть если — регулярное выражение, то для него найдется самое левое вхождение в текст.
function matchHere(regexp: String, text: String): boolean if regexp == '\0' return true if regexp == '*' return matchStar(regexp, regexp, text) if regexp == '$' and regexp == '\0' return text == '\0' if text != '\0' and (regexp == '.' or regexp == text) return matchHere(regexp, text) return false
Основная часть работы сделана в , которая сопоставляет регулярное выражение с текстом в текущей позиции. Функция пытается сопоставить первый символ регулярного выражения с первым символом текста. В случае успеха мы можем сравнить следующий символ регулярного выражения со следующим символом текста, вызвав рекурсивно. Иначе нет совпадения с регулярным выражением в текущей позиции текста.
function matchStar(c: char, regexp: String, text: String): boolean int i = 0 while i text.length and (text == c or c == '.') if matchHere(regexp, text) return true i++ return false
Рассмотрим возможные случаи:
- Если в ходе рекурсии регулярное выражение осталось пустым то текст допускается этим регулярным выражением.
- Если регулярное выражение имеет вид , то вызывается функция которая пытается сопоставить повторение символа , начиная с нуля повторений и увеличивая их количество, пока не найдет совпадение с оставшимся текстом. Если совпадение не будет найдено, то регулярное выражение не допускает текст. Текущая реализация ищет «кратчайшее совпадение», которое хорошо подходит для сопоставления с образцом, как в grep, где нужно как можно быстрее найти совпадение. «Наидлиннейшее совпадение» более интуитивно и больше подходит для текстовых редакторов, где найденное заменят на что-то. Большинство современных библиотек для работы с регулярными выражениями предоставляют оба варианта.
- Если регулярное выражение это , то оно допускает этот текст тогда и только тогда, когда текст закончился.
- Если первый символ текста совпал с первым символом регулярного выражения, то нужно проверить совпадают ли следующий символ регулярного выражения со следующим символом текста, сделав рекурсивный вызов .
- Если все предыдущие попытки найти совпадения провалились, то никакая подстрока из текста не допускается регулярным выражением.
Модификацииправить
Немного изменим функцию для поиск самого левого и самого длинного вхождения :
- Найдем максимальную последовательность подряд идущих символов . Назовем ее .
- Сопоставим часть текста без с остатком регулярного выражения.
- Если части совпали, то текст допускается этим регулярным выражением. Иначе, если пусто, то текст не допускается этим регулярным выражением, иначе убираем один символ из и повторяем шаг .
Псевдокодправить
function matchStar(c: char, regexp: String, text: String): boolean int i for (i = 0; text != '\0' and (text == c or c == '.'); i++) while i 0 if matchHere(regexp, text) return true i-- return false
Пример
Допустим, у нас есть строка, и мы хотим проверить, что она состоит из слов , после каждого слова может быть пробел .
Используем регулярное выражение , которое задаёт 0 или более таких слов.
Проверим, чтобы убедиться, что оно работает:
Результат верный. Однако, на некоторых строках оно выполняется очень долго. Так долго, что интерпретатор JavaScript «зависает» с потреблением 100% процессора.
Если вы запустите пример ниже, то, скорее всего, ничего не увидите, так как JavaScript «подвиснет»
В браузере он перестанет реагировать на другие события и, скорее всего, понадобится перезагрузить страницу, так что осторожно с этим:. Некоторые движки регулярных выражений могут справиться с таким поиском, но большинство из них – нет
Некоторые движки регулярных выражений могут справиться с таким поиском, но большинство из них – нет.
Точка и перенос строки
Для поиска в многострочном режиме почти все модификации перловых регэкспов используют специальный multiline-флаг.
И javascript здесь не исключение.
Попробуем же сделать поиск и замену многострочного вхождения. Скажем, будем заменять на тэг подчеркивания: :
function bbtagit(text) { text = text.replace(/\(.*?)\[\/u\]/gim, '<u>$1</u>') return text } var line = "мой\n текст" alert( bbtagit(line) )
Попробуйте запустить. Заменяет? Как бы не так!
Дело в том, что в javascript мультилайн режим (флаг ) влияет только на символы ^ и $, которые начинают матчиться с началом и концом строки, а не всего текста.
Точка по-прежнему — любой символ, кроме новой строки. В javascript нет флага, который устанавливает мультилайн-режим для точки. Для того, чтобы заматчить совсем что угодно — используйте .
Работающий вариант:
function bbtagit(text) { text = text.replace(/\(*)\[\/u\]/gim, '<u>$1</u>') return text } var line = "мой\n текст" alert( bbtagit(line) )
Удаляем заглавные буквы с помощью строк и регулярных выражений
Теперь у нас есть строка с кучей ненужных прописных букв. Вы догадались, как их удалить? Во-первых, нам нужно выбрать все заглавные буквы. Затем используем поиск набора символов с помощью глобального модификатора //g. Мы снова будем использовать метод replace, но как в этот раз сделать строчной символ?
Пример:
Квадратные скобки задают диапазон символов (в данном случае — любые буквы английского алфавита в нижнем регистре). Все, что попадает в этот диапазон, будет соответствовать шаблону. Диапазоны символов могут быть разными. Это могут быть буквы в верхнем регистре (тогда диапазон будет выглядеть как ) или цифры ().
Если ваш диапазон должен охватывать все буквенно-цифровые символы и символ подчеркивания, то шаблон может выглядеть следующим образом: .
Backreferences в паттерне и при замене
Иногда нужно в самом паттерне поиска обратиться к предыдущей его части.
Например, при поиске BB-тагов, то есть строк вида , и . Или при поиске атрибутов, которые могут быть в одинарных кавычках или двойных.
Обращение к предыдущей части паттерна в javascript осуществляется как \1, \2 и т.п., бэкслеш + номер скобочной группы:
text = ' a b c ' var reg = /\)\](.*?)\[\//*u*/\1/*/u*/\]/ text = text.replace(reg, '<$1>$2</$1>') alert(text)
Обращение к скобочной группе в строке замены идет уже через доллар: . Не знаю, почему, наверное так удобнее..
P.S. Понятно, что при таком способе поиска bb-тагов придется пропустить текст через замену несколько раз — пока результат не перестанет отличаться от оригинала.
Metacharacters
A metacharacter is simply an alphabetical character preceded by a backslash that acts to give the combination a special meaning.
For instance, you can search for a large sum of money using the ‘\d’ metacharacter: /(+)000/, Here \d will search for any string of numerical character.
The following table lists a set of metacharacters which can be used in PERL Style Regular Expressions.
Sr.No. | Character & Description |
---|---|
1 |
. a single character |
2 |
\s a whitespace character (space, tab, newline) |
3 |
\S non-whitespace character |
4 |
\d a digit (0-9) |
5 |
\D a non-digit |
6 |
\w a word character (a-z, A-Z, 0-9, _) |
7 |
\W a non-word character |
8 |
a literal backspace (special case). |
9 |
matches a single character in the given set |
10 |
matches a single character outside the given set |
11 |
(foo|bar|baz) matches any of the alternatives specified |
Quantifiers
The frequency or position of bracketed character sequences and single characters can be denoted by a special character. Each special character has a specific connotation. The +, *, ?, and $ flags all follow a character sequence.
Sr.No. | Expression & Description |
---|---|
1 |
p+ It matches any string containing one or more p’s. |
2 |
p* It matches any string containing zero or more p’s. |
3 |
p? It matches any string containing at most one p. |
4 |
p{N} It matches any string containing a sequence of N p’s |
5 |
p{2,3} It matches any string containing a sequence of two or three p’s. |
6 |
p{2, } It matches any string containing a sequence of at least two p’s. |
7 |
p$ It matches any string with p at the end of it. |
8 |
^p It matches any string with p at the beginning of it. |
Examples
Following examples explain more about matching characters.
Sr.No. | Expression & Description |
---|---|
1 |
It matches any string not containing any of the characters ranging from a through z and A through Z. |
2 |
p.p It matches any string containing p, followed by any character, in turn followed by another p. |
3 |
^.{2}$ It matches any string containing exactly two characters. |
4 |
<b>(.*)</b> It matches any string enclosed within <b> and </b>. |
5 |
p(hp)* It matches any string containing a p followed by zero or more instances of the sequence hp. |
test()
Для работы с регулярными выражениями есть несколько методов. Простейший из них —. При использовании этого метода необходимо передать функции проверяемую строку в качестве аргумента. В результате метод возвращает булево значение: — если в строке есть совпадения с шаблоном, — если совпадений нет.
// Синтаксис метода test()// /шаблон/.test('проверяемый текст')// Проверка строки,// когда test() не находит совпаденийmyPattern.test('There was a cat and dog in the house.')// false// Создание переменной,// которой присваивается текст для проверкиconst myString = 'The world of code.'// Создание шаблонаconst myPattern = /code/// Проверка текста с помощью шаблона,// когда test() находит совпадениеmyPattern.test(myString)// true
Создаем собственные регулярные выражения JavaScript
Существует два способа создания регулярного выражения: с использованием литерала регулярного выражения или с помощью конструктора регулярных выражений. Каждый из них представляет один и тот же шаблон: символ «c», за которым следует «a», а затем символ «t».
// литерал регулярного выражения заключается в слэши (/) var option1 = /cat/; // Конструктор регулярнго выражения var option2 = new RegExp("cat");
Как правило, если регулярное выражение остается константой, то есть не будет меняться, лучше использовать литерал регулярного выражения. Если оно будет меняться или зависит от других переменных, лучше использовать метод с конструктором.
Содержимое скобок в match
Скобочные группы нумеруются слева направо. Поисковый движок запоминает содержимое, которое соответствует каждой скобочной группе, и позволяет получить его в результате.
Метод , если у регулярного выражения нет флага , ищет первое совпадение и возвращает его в виде массива:
- На позиции будет всё совпадение целиком.
- На позиции – содержимое первой скобочной группы.
- На позиции – содержимое второй скобочной группы.
- …и так далее…
Например, мы хотим найти HTML теги и обработать их. Было бы удобно иметь содержимое тега (то, что внутри уголков) в отдельной переменной.
Давайте заключим внутреннее содержимое в круглые скобки: .
Теперь получим как тег целиком , так и его содержимое в виде массива:
Скобки могут быть и вложенными.
Например, при поиске тега в нас может интересовать:
- Содержимое тега целиком: .
- Название тега: .
- Атрибуты тега: .
Заключим их в скобки в шаблоне: .
Вот их номера (слева направо, по открывающей скобке):
В действии:
По нулевому индексу в всегда идёт полное совпадение.
Затем следуют группы, нумеруемые слева направо, по открывающим скобкам. Группа, открывающая скобка которой идёт первой, получает первый индекс в результате – . Там находится всё содержимое тега.
Затем в идёт группа, образованная второй открывающей скобкой – имя тега, далее в будет остальное содержимое тега: .
Соответствие для каждой группы в строке:
Даже если скобочная группа необязательна (например, стоит квантификатор ), соответствующий элемент массива существует и равен .
Например, рассмотрим регулярное выражение . Оно ищет букву , за которой идёт необязательная буква , за которой, в свою очередь, идёт необязательная буква .
Если применить его к строке из одной буквы , то результат будет такой:
Массив имеет длину , но все скобочные группы пустые.
А теперь более сложная ситуация для строки :
Длина массива всегда равна . Для группы ничего нет, поэтому результат: .
Назад к словам и строкам
В начальном примере, когда мы ищем слова по шаблону в строке вида , происходит то же самое.
Дело в том, что каждое слово может быть представлено как в виде одного , так и нескольких:
Человеку очевидно, что совпадения быть не может, так как эта строка заканчивается на восклицательный знак , а по регулярному выражению в конце должен быть символ или пробел . Но движок этого не знает.
Он перебирает все комбинации того, как регулярное выражение может «захватить» каждое слово, включая варианты как с пробелами , так и без (пробелы ведь не обязательны). Этих вариантов очень много, отсюда и сверхдолгое время выполнения.
Указание количества повторений символов в тексте
Все приведенные выше регулярные выражения будут совпадать только с одним символом. Чтобы указать, сколько символов должно быть тексте, чтобы произошло совпадение вы можете использовать квантификаторы.
+ – Обозначает одно или более совпадение. Например, чтобы регулярное выражение совпало с набором символов “ABD12D” нужно использовать \w+.
* – Обозначает ноль или более символов. Например, под выражение b\w* подойдут следующие сочетания символов: “b”, “bat”, “bajhdsfbfjhbe”. В данном случае мы ищем соответствие нулевому или более количеству символов в словах после буквы “b”.
{m, n} – Соответствует не менее m и не более n вхождений предыдущего символа. {m,} будет соответствовать не менее, чем m вхождений, верхнего предела в этом случае нет. {k} будет соответствовать точному количеству (k) вхождений предыдущего символа.
? – Обозначает ноль или один символ. Например, это может быть полезно при сопоставлении двух вариантов написания для одной и той же слова. Выражению будут соответствовать оба слова: “behavior” и “behaviour”.
| – Соответствует выражению до или после символа |. Например, выражению /se(a|e)/ — соответсвуют оба слова: “see” и “sea”.
МетаСимволы
Для указания регулярных выражений используются метасимволы. В приведенном выше примере ( ) является метасимволом.
Метасимволы — это символы, которые интерпретируются особым образом механизмом 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 не интерпретирует особым образом.
Если вы не уверены, имеет ли символ особое значение или нет, вы можете экранировать его косой чертой . Это гарантирует, что экранированный символ не будет компилироваться по-особенному.
Итого
Существуют следующие символьные классы:
- – цифры.
- – не цифры.
- – пробельные символы, табы, новые строки.
- – все, кроме .
- – латиница, цифры, подчёркивание .
- – все, кроме .
- – любой символ, если с флагом регулярного выражения , в противном случае любой символ, кроме перевода строки .
…Но это не всё!
В кодировке Юникод, которую JavaScript использует для строк, каждому символу соответствует ряд свойств, например – какого языка это буква (если буква), является ли символ знаком пунктуации, и т.п.
Можно искать, в том числе, и по этим свойствам. Для этого нужен флаг , который мы рассмотрим в следующей главе.