Приветствую всех читателей данной публикации, а также моих горячо любимых подписчиков. Одними из самых сложных для понимания и усвоения материала являются регулярные выражения в JavaScript. И не только в этом языке, а и во многих других (C-подобных, Python, JSON и т.д.). Данная тема вызывает множество вопросов как у новичков, так и у более опытных разработчиков.
Поэтому я решил ввести вас в курс дела и заложить фундамент для будущего возможного изучения вами регулярных выражений. В статье вы найдете определение и объяснение, для чего существуют такие виды выражений, ознакомитесь с базовыми инструментами и командами управления, а также сможете опробовать примеры. Давайте приступим к разбору полетов!
Всесильные регулярные выражения и их особенности
Если вы хоть когда-нибудь сталкивались с данной тематикой, то уже с легкостью в коде отыщите обсуждаемый объект. Для новичков, к примеру, проверка email-а покажется просто непонятным хаотичным набором различных символов.
Var pattern = /^[a-z0-9_-]+@[a-z0-9-]+\.[a-z]{2,6}$/i;
А более опытный разработчик поймет, что данное выражение проверяет введенное мыло на корректность. Таким образом, в написанном должна быть почта, состоящее из цифр, букв, знака тире и/или нижнего подчеркивания, после обязательно должен присутствовать один знак собачки, за которым следуют буквы, тире и цифры, а далее точка и от двух до шести символов.
Это и есть основная отличительная черта регулярных выражений. Они абсолютно не похожи ни на какие известные вам ранее средства программирования.
Итак, регулярные выражение по-простому можно назвать образцом, шаблоном, по которому идет сопоставление символов в строках. Благодаря им можно производить поиск, проверку и замену строковых значений.
Главным их преимуществом является удобный способ записи универсальных формул проверки значений.
С их помощью проверяют формы на корректность введенных данных. В качестве примера можно привести проверки правильного написания email-ов, мобильных и стационарных телефонных номеров, корректность вводимых имен или логинов и т.д.
Вот пример тестирования на валидность мобильного номера вида (+ХХХХХХХХХХХХ):
var reg = /^\+[\d\(\)\ -]{10,13}\d$/;
Также с помощью шаблонов можно производить поиск совпадений слов/выражений в тексте с искомым значением.
Правила написания шаблонов в JavaScript
В JS сами регулярные выражения являются объектами и создаются в специальном конструкторе RegExp. Существует два способа инициализации таких объектов: литеральное выражение (/шаблон/флаг) и с помощью конструктора (new RegExp («шаблон» [, флаг]); ). При этом любая строка-образец в обеих вариантах обязательно должна содержать в себе собственно сам паттерн и при надобности флаги.
К самим выражением мы подойдем чуть позже, а пока разберем, что же под собой подразумевает такой параметр, как флаг.
Итак, flag – это инструмент для установки глобального или регистронезависимого поиска. В JS можно использовать четыре вида флага. При этом вы можете их прописывать как по отдельности, так и комбинировать в разном порядке и количестве. Хочу заметить, что от смены порядка результат выполнение не изменится.
Флаг | Предназначение |
m | Определяет многострочный поиск, т.е. образец сравнивается со всеми буквами, цифрами или другими знаками, которые разделены между собой известными пробельными символами. |
i | Поиск подстрок осуществляется без учета регистра. |
y | Выполнение проверки переменных начинается от символа, находящегося на позиции свойства под названием lastIndex. |
g | Задает глобальный поиск, после выполнения которого будут выведены все возможные совпадения. |
Ну а теперь давайте рассмотрим первый простой пример для понимания происходящего. С помощью переменной regExp я проверяю, есть ли вхождение в text слова «вариант». При этом я хочу, чтобы вывелись все случаи вхождения без учета регистра.
1 2 3 4 5 6 | <script> var regExp = /вариант/gi; var text = "Вариант 1. напишите стих, состоящий из четырех строк. Вариант 2. Допишите стих из варианта 1."; var myArray = text.match(regExp ); alert(myArray); </script> |
Заметки о методах
Для работы с регулярными выражениями используется семь методов. Начнем разбор по порядку.
Search ()
Используется для нахождения позиции вхождения первого совпадения.
1 2 3 4 5 6 | <script> var regExp = /рыб/gi; var text = "Покупайте речную рыбу!"; var myArray = text.search(regExp ); alert(myArray); //Ответ: 17 </script> |
Match ()
Работает в двух режимах в зависимости от того, укажете ли вы опциональный флаг g или нет.
Если /g отсутствует, то в результате будет получен массив из одного элемента и с возможностью просмотра дополнительных свойств input (строка, в которой осуществлялся поиск совпадений) и index (позиция результата; если подстрока не найдена, то покажет -1).
1 2 3 4 5 6 7 8 | <script> var regExp = /12.02/; var text = "11.02 - Концерт. 12.02 - Мастер-класс."; var myArray = text.match(regExp ); alert( myArray[0] ); alert( myArray.input ); //11.02 - Концерт. 12.02 - Мастер-класс. alert( myArray.index ); //17 </script> |
Если же вы используете глобальный поиск, то возможность просмотра дополнительных свойств пропадает, а в массиве вернутся все совпадения.
Split ()
Как и в некоторых других языках программирования, метод Split () разбивает значение строковой переменной на подстроки по заданному разделителю.
1 2 3 4 | <script> var text = "Пусть все будет хорошо"; alert(text.split(' ')); //Пусть,все,будет,хорошо </script> |
В качестве разделителя можно передавать как строковое значение, так и регэксп.
Replace ()
Очень удобный инструмент для нахождения и замены символов в задачах различной сложности. По умолчанию изменяет только первое совпавшее вхождение, однако это исправимо благодаря такой удобной штуке, как /g.
1 2 3 4 | <script> var text = "Ты пробежал 3 км за 13 и 25 минут."; alert( text.replace( / и /g, "," )); // Ты пробежал 3 км за 13,25 минут </script> |
Exec ()
До этого все методы принадлежали к классу String. А оставшиеся два предоставляются классом RegExp.
Итак, текущий метод является дополнением к первым двум описанным методам. Он также ищет все вхождения и еще скобочные группы. Без указания флага g exec () работает, как match (). В противном случае совпадение запоминается, а его позиция записывается в lastIndex.
Последующий поиск продолжается с установленной позиции. Если далее совпадений больше не было, то lastIndex сбрасывается в 0.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <script> var str = 'Сорок сорок сидели на трубе'; var expresion = /сорок/ig; var res; alert( "lastIndex: " + expresion.lastIndex ); while (res = expresion.exec(str)) { alert( 'Найдено: ' + res[0] + ' на позиции: ' + res.index ); alert( 'А теперь lastIndex равен: ' + expresion.lastIndex ); } alert( 'Под конец lastIndex сбрасывается в: ' + expresion.lastIndex ); </script> |
Test ()
Данный инструмент проверяет, а есть ли хоть один результат совпадения строк. Если есть, то возвращает булево значение true, иначе – false.
1 2 3 4 | <script> var expresion = /крас/gi; alert( expresion.test("Ах, какая красна девица! красавица!")); //true </script> |
Вот я и рассказал вам основы такого механизма, как регулярные выражения. Для лучшего усвоения материала читайте и другие статьи на данную тематику на моем блоге, а также становитесь подписчиками и делитесь интересными ссылками с друзьями. Пока-пока!
С уважением, Роман Чуешов
Регулярные выражения действуют как фильтр, отыскивая нужную информацию и оставляя за бортом излишнюю. Поиск, встроенный в сайты наверно как раз использует регулярные выражения.
Регулярные выражения вещь мощная, но вызывающая споры. В первую очередь это касается замедления работы программы из-за регулярных выражений.
Смотрю по примерам, в JavaScript шаблон регулярного выражения можно писать на русском языке, т.е. в utf-8, что однозначно плюс языка. В Python по моему это нельзя.
По ходу написания комментарев такая мысль пришла, что обычные текстовые редакторы внутри себя имеют механизм поиска нужных пользователю слов, основанного на принипах регулярного выражения метода Search или Match, но я могу заблуждаться.
По проверке регулярки введенного мыла на корректность из этой статьи. Что такое прямой слэш /, зкранирование последущего символа? Разве для экранирования метасимволов не используется обратный слэш \?
Если прямой слэш в джаве для экранирования, то его можно было поместить внутри класса a-z0-9_- , потому что внутри класса метасимволы становятся обычными символами. Например, a-z0-9_-^ в квадратных скобках разумеется.