Что такое регулярные выражения

В большинстве своем 80% современного программирования сведены к анализу и работе с информацией. А информация всегда предоставляется нам в текстовой форме, просто потому, что другие ее формы анализу так легко не поддаются. Проще говоря одна из первых задач, с которой сталкивается любой программист, это парсинг информации. А где парсинг, там и регулярные выражения. О них мы сегодня и поговорим ибо выяснилось, что многие понятия не имеют, что это такое, и с чем это едят. После прочтения этой статьи вы поймете как создавать свои регулярные выражения, а так-же как с ними работать. Ниже даже пример на php есть.

О регулярных выражениях

И так, что же такое регулярное выражение?

/<as*href='(.+?)'/

Я, таки, могу прямо сюда скопировать описание из википедии, но думаю лучше просто показать, ибо объяснить как оно работает на словах очень сложно. Тут надо понять. Причем самому. Но определение я все-таки дам:

Регулярное выражение — это маска, по которой можно искать определенные данные в тексте или искать и заменять эти самые данные.

Что позволяют делать эти «магические конструкции» и почему так важно уметь их использовать? На самом деле все просто.
Предположим, нам надо найти все теги <div>
в строке. Пишем регулярное выражение, скармливаем ему строчку и все!

preg_match("/<div[^>]*>(.+?)</div>/is",$data,$matches);

Начинающий кодер, таки, может спросить: но разве то-же самое нельзя сделать через strpos и substr? Да, это можно сделать, но давайте просто сравним количество кода:

$spos=stripos($html,"<div");  $lpos=stripos($html,"</div");  if($spos !== false && $lpos !== false)  $result = substr($spos,$spos-$lpos);  

Как вы видите, регулярные выражения экономят кучу времени. Да, для новичка они выглядят как нечто ужасное, сродни ктулху. Однако, страшного там ничего нет и сегодня вы в этом убедитесь.

Учимся понимать регулярные выражения

Прежде чем что-то писать или объяснять, я бы хотел представить вам инструмент для работы с регулярками, это RegExr. Откройте его в новой вкладке и прорабатывайте там все примеры, которые я буду приводить.
Начнем с простого, с чего начинал я сам. С получения содержимого атрибута тега. Предположим нам надо взять атрибут href="ссылка"
из тега ссылки. Как нам это сделать?
Давайте откроем ide RegExr и в нижнем поле впишем html код ссылки.

Что такое регулярные выражения

Теперь собственно составим регулярку. Что мы знаем?
1. Атрибут начинается с href и содержит знак равно, с двумя кавычками по краям.
2. Нужные нам данные находятся между этих кавычек и эти данные могут меняться случайный образом

Пункт 1 решается крайне просто. Давайте укажем в верхнем поле известные нам данные:

Что такое регулярные выражения

Теперь собственно обратимся к пункту номер 2.

Как указать строку, которая меняется случайным образом? Чтобы понять строку, надо понять из чего она состоит. (с) Любая случайная строка состоит из случайных букв и(или) символов, которые указаны в ней в различном (любом) порядке. Чтож, откроем справочник регулярных выражений. Лучший из встреченных мной, это справочник от microsoft. Не смотрите, что там указано, якобы справочник для javascript. В большинстве своем регулярные выражения работают одинаково на любых языках от C# до php. Ищем там описание кода для любого символа:

Что такое регулярные выражения

Как мы видим, в регулярке за любой символ отвечает точка (.), самая обыкновенная черная точка. Вот ее мы и укажем после href=""

Что такое регулярные выражения

Ничего? Да, все верно, регулярка не работает, (ожидаемо). А все потому, что мы указали 1 символ. То есть, если указать в атрибуте href всего 1 символ, то он выражение сработает. Давайте убедимся в этом:

Что такое регулярные выражения

Теперь перед нами стоит задача указать интерпретатору, что символов может быть больше 1 в несколько раз. Тут есть несколько различных путей, но остановимся на одном. Это банальное повторение предыдущего символа нужное кол-во раз. Ищем в справочнике по ссылке выше информацию об повторениях.

Что такое регулярные выражения

И так, за повторения отвечает или звездочка или знак плюса. Причем разница между ними есть. Выражение со звездочкой будет работать даже если символа вообще нет в анализируемом документе. Берем любой из них, я бы советовал вам взять для начала звездочку. Со временем научитесь их применять в зависимости от ситуации.


Что такое регулярные выражения

Ура! Заработало. Таким образом можно сказать мы написали наше первое регулярное выражение. Но не будем торопиться, ибо нет предела совершенству. Предположим, что нам надо получить из текста именно ту часть которая находится между кавычками. Делает ли это наше выражение? Нет. Оно получает полностью весь блок. Дабы убедиться наведем на мышь на выделенный текст:

Что такое регулярные выражения

То есть задача еще не выполнена. Снова открываем справочник и ищем как захватить часть регулярного выражения.

Что такое регулярные выражения

Простые кавычки () позволяют нам это сделать, хотя описание в документации как всегда крайне поехавшее. Укажем кавычки в нашем редакторе и посмотрим на результат.

Что такое регулярные выражения

Отлично. Теперь результатом работы регулярного выражения будет массив содержащий как полный текст искомого блока, так и содержимое этого самого блока.

В php эта регулярка переносится так:

/href="(.*)"/    

Ленивые и Жадные квантификаторы

Собственно разница между этими квантификаторами в подходе к выборке данных. Жадное квантификаторы берут Максимально возможный текстовый блок. А Ленивые хапают то, до чего быстрее всего дотягиваются. Ибо остальное собирать — «лень».
В нашем случае ленивое регулярное выражение выглядит так:

/href="(.*?)"/

Я добавил знак вопроса после звездочки. Читаем:

Что такое регулярные выражения

Дабы осветить эту тему на примере нам придется открыть php sandbox, которая позволяет запускать php код прямо из браузера.

Код который мы будем запускать приведен ниже:

// Дублируем дважды нашу ссылку  $str = '<a href="http://aftamat4ik.ru">Это ссылка из которой мы будем брать href</a>  <a href="http://aftamat4ik.ru">Это ссылка из которой мы будем брать href</a>  ';   // Жадно   preg_match('/href="(.*)"/is', $str, $matches);   echo "Жадное регулярное выражение: ".$matches[1].PHP_EOL;; echo '-------------------------'.PHP_EOL;     // Лениво   preg_match('/href="(.*?)"/', $str, $matches); echo "Ленивое регулярное выражение: ".$matches[1].PHP_EOL;      

Результат выполнения этого кода наглядно покажет вам отличия жадного и ленивого выражения друг от друга.
Что такое регулярные выражения
Как вы видите, без вопросительного знака в коде регулярного выражения нам никак не обойтись, ибо без него выражение будет захватывать лишнюю информацию, превращая все в трэш угар и содомию.

/href="(.*?)"/

Но это еще не все!

Унифицируем регулярное выражение.

Переключимся назад к RegExr и представим ситуацию, при которой html код, анализируемый нами, содержит в href не только двойные, но и одинарные кавычки.
Что такое регулярные выражения

Не работает! Подходящий способ решения — это указать вместо кавычек, набор символов, где будут оба вида этих элементов. За создание набора символов отвечают квадратные скобки:

Что такое регулярные выражения

Собственно делается это так: ["'] — эта последовательность символов соответствует как " и так и '.
Итоговое регулярное выражение примет вид:

/href=['"](.*?)['"]/    

Что такое регулярные выраженияКак вы видите, все определяется правильно. Но, обратите внимание на последнюю ссылку, где имеется href=' и ", то есть совершенно не работающий html код, который, тем не менее, определяется как работающий. Что делать, если его надо исключить? Используем ссылки.

Ссылки в регулярных выражениях

Ссылки позволяют нам, в самом выражении, ссылаться на его элементы. Например наш элемент — href="" имеет два повторяющихся символа, на которые мы и будем опираться. Это " и " или ' и '. Так как они повторяются, мы можем взять такой символ и сослаться на него второй раз, а не указывать снова. Тогда получится отфильтровать ошибку, ведь если мы ссылаемся на кавычку вида " то регулярное выражение будет искать именно ее. Чтобы сослаться, надо просто указать конструкцию вида: число, к примеру 1 где цифра — номер скобочки. Да, элемент на который мы ссылаемся, должен быть в круглых скобках. В нашем случае:
Берем выражение ['"] и оборачиваем в кавычки (['"]) а потом просто ссылаемся на кавычки через 1
В итоге получим:

/href=(['"])(.*?)/    

Что такое регулярные выражения

 

Ура! Последняя строчка не учитывается.

В 90% случаев этих знаний вам хватит с лихвой для парсинга чего угодно, откуда угодно.

Пример парсинга информации

Давайте, используя регулярные выражения и php, спарсим, в маленьком скрипте, например, эту страницу — хабр. Для отработки навыков самое оно будет.

В php за работу регулярок отвечают функции preg_match и preg_match_all, которые и будут использоваться в данном примере.

Для начала, давайте определим регулярное выражение, которое соответствует заголовку статьи.

Что такое регулярные выражения

Я работаю в браузере гугл хром, поэтому открываю html-код страницы и ищу там блок с материалом.

Что такое регулярные выражения

и далее сюда —

Что такое регулярные выражения

Тут выделен блок, отвечающий за название материала, которое мы и будем парсить в первую очередь. Чтож, берем его, копируем его в regexr и подбираем регулярное выражение!

Что такое регулярные выражения

Как вы видите в Group#1 находится чистый заголовок. Разберем то, что я написал в выражении:

   
/class=['"]post__title-arrow.+</span>[nst]+?<span>(.+?)</span>/

Элемент (.+?), представляющий из себя строку не нулевой длинны, обрамленный спереди в строку с атрибутом class содержащий блок post__title-arrow и любые .+ символы после этого блока, а так-же два элемента </span> и <span>, разделенные меж собой последовательностью из переноса строки, таба и пробела повторенных несколько раз [nst]+? заканчивается на </span> Да… описание работы выглядит как … в общем не пытайтесь это повторить.

preg_match("/class=['"]post__title-arrow.+</span>[nst]+?<span>(.+?)</span>/",$html, $titles);

К стати в блоке ['"] символ означает экранирование кавычки. Он не учитывается в итоговом выражении и всего-лишь помогает интерпретатору воспринимать строку целиком. Осталось вставить эту регулярку в php с экранированием и обрамлением в символы границ.

Итоговый php код выглядит так:

$html = file_get_contents("https://habrahabr.ru/sandbox/15940/");  preg_match("~class=['"]post__title-arrow.+</span>[nst]+?<span>(.+?)</span>~",$html,$titles);    echo $titles[1];    

Функция preg_match анализирует строку $html и ищет там блок, который подходит под регулярное выражение, после чего извлекает из этого блока группы в круглых скобочках () и помещает их в массив. В данном случае этот массив называется $titles и $titles[1] собственно вывод первой(и единственной в данном случае) кавычки.
И результат выполнения кода выглядит так:

Что такое регулярные выражения

Точно так-же определяем регулярное выражение для текста статьи. Опять копирем блок отвечающий за данный текст в regexr и подбираем выражение, а потом просто вставляем его в preg_match с экранированием.

Что такое регулярные выражения

И выражение:

/class=['"]content html_format['"]>([sS]+?)<div class=['"]post__tags/

Тут вы видите новый блок [sS]+?, что он значит? Заголовок статьи — не имеет в себе переносов строки и поэтому там можно было справиться банальным повторением символа .+? тут же у нас есть переносы и пробелы. Ибо это контент. Чтобы решить проблему мы просто помещаем внутрь кавычек символ s — пробела и S — все что угодно, кроме пробела и указывам, что этот блок повторяется несколько раз через +?

Результат парсинга будет таков —

Что такое регулярные выражения

И вот мы спарсили сайт! Да, так это работает. Человек, потративший пару дней на изучение регулярок, в последствии сможет спарсить все что угодно!

Ну и на последок, разумеется, общий код.

  // Тестовый парсер  header('Content-Type: text/html; charset=utf-8');    // Определяем заголовок материала  $html = file_get_contents("https://habrahabr.ru/sandbox/15940/");    preg_match("~class=['"]post__title-arrow.+</span>[nst]+?<span>(.+?)</span>~",$html,$titles);  preg_match("~class=['"]content html_format['"]>([sS]+?)<div class=['"]post__tags~",$html,$contents);    echo "<h3>".$titles[1]."</h3>";  echo $contents[1];

С небольшими отличиями, регулярные выражения одинаковы везде. В js,php,c# или любом другом языке программирования. Синтаксис везде один и тот-же, а значит и этот метод будет актуален и там тоже. К слову, несмотря на все свистопляски с regexr,которые я тут описал, опытный кодер способен написать регулярку на лету, не заморачиваясь. Учитесь, хехе.
Ну и, разумеется, вот исходник, если вам интересно:

aftamat4ik.ru

Что такое регулярные выражения?

Если вам когда-нибудь приходилось работать с командной строкой, вы, вероятно, использовали маски имён файлов. Например, чтобы удалить все файлы в текущей директории, которые начинаются с буквы “d”, можно написать rm d*.

Регулярные выражения представляют собой похожий, но гораздо более сильный инструмент для поиска строк, проверки их на соответствие какому-либо шаблону и другой подобной работы. Англоязычное название этого инструмента — Regular Expressions или просто RegExp. Строго говоря, регулярные выражения — специальный язык для описания шаблонов строк.

Реализация этого инструмента различается в разных языках программирования, хоть и не сильно. В данной статье мы будем ориентироваться в первую очередь на реализацию Perl Compatible Regular Expressions. 

Основы синтаксиса

В первую очередь стоит заметить, что любая строка сама по себе является регулярным выражением. Так, выражению Хаха, очевидно, будет соответствовать строка “Хаха” и только она. Регулярные выражения являются регистрозависимыми, поэтому строка “хаха” (с маленькой буквы) уже не будет соответствовать выражению выше.

Однако уже здесь следует быть аккуратным — как и любой язык, регулярные выражения имеют спецсимволы, которые нужно экранировать. Вот их список: . ^ $ * + ? { } [ ] | ( ). Экранирование осуществляется обычным способом — добавлением перед спецсимволом.

Набор символов

Предположим, мы хотим найти в тексте все междометия, обозначающие смех. Просто Хаха нам не подойдёт — ведь под него не попадут “Хехе”, “Хохо” и “Хихи”. Да и проблему с регистром первой буквы нужно как-то решить.

Здесь нам на помощь придут наборы — вместо указания конкретного символа, мы можем записать целый список, и если в исследуемой строке на указанном месте будет стоять любой из перечисленных символов, строка будет считаться подходящей. Наборы записываются в квадратных скобках — паттерну [abcd] будет соответствовать любой из символов “a”, “b”, “c” или “d”.

Внутри набора большая часть спецсимволов не нуждается в экранировании, однако использование перед ними не будет считаться ошибкой. По прежнему необходимо экранировать символы “” и “^”, и, желательно, “]” (так, [][] обозначает любой из символов “]” или «[», тогда как [[]х] – исключительно последовательность “[х]”). Необычное на первый взгляд поведение регулярок с символом “]” на самом деле определяется известными правилами, но гораздо легче просто экранировать этот символ, чем их запоминать. Кроме этого, экранировать нужно символ «-», он используется для задания диапазонов (см. ниже).

Если сразу после [ записать символ ^, то набор приобретёт обратный смысл — подходящим будет считаться любой символ кроме указанных. Так, паттерну [^xyz] соответствует любой символ, кроме, собственно, “x”, “y” или “z”.

Итак, применяя данный инструмент к нашему случаю, если мы напишем [Хх][аоие]х[аоие], то каждая из строк “Хаха”, “хехе”, “хихи” и даже “Хохо” будут соответствовать шаблону.

Предопределённые классы символов

Для некоторых наборов, которые используются достаточно часто, существуют специальные шаблоны. Так, для описания любого пробельного символа (пробел, табуляция, перенос строки) используется s, для цифр — d, для символов латиницы, цифр и подчёркивания “_” — w.

Если необходимо описать вообще любой символ, для этого используется точка — .. Если указанные классы написать с заглавной буквы (S, D, W) то они поменяют свой смысл на противоположный — любой непробельный символ, любой символ, который не является цифрой, и любой символ кроме латиницы, цифр или подчёркивания соответственно.

Также с помощью регулярных выражений есть возможность проверить положение строки относительно остального текста. Выражение b обозначает границу слова, B — не границу слова, ^ — начало текста, а $ — конец. Так, по паттерну bJavab в строке “Java and JavaScript” найдутся первые 4 символа, а по паттерну bJavaB — символы c 10-го по 13-й (в составе слова “JavaScript”).

Диапазоны

У вас может возникнуть необходимость обозначить набор, в который входят буквы, например, от “б” до “ф”. Вместо того, чтобы писать [бвгдежзиклмнопрстуф] можно воспользоваться механизмом диапазонов и написать [б-ф]. Так, паттерну x[0-8A-F][0-8A-F] соответствует строка “xA6”, но не соответствует “xb9” (во-первых, из-за того, что в диапазоне указаны только заглавные буквы, во-вторых, из-за того, что 9 не входит в промежуток 0-8).

Механизм диапазонов особенно актуален для русского языка, ведь для него нет конструкции, аналогичной w. Чтобы обозначить все буквы русского алфавита, можно использовать паттерн [а-яА-ЯёЁ]. Обратите внимание, что буква “ё” не включается в общий диапазон букв, и её нужно указывать отдельно.

Квантификаторы (указание количества повторений)

Вернёмся к нашему примеру. Что, если в “смеющемся” междометии будет больше одной гласной между буквами “х”, например “Хаахаааа”? Наша старая регулярка уже не сможет нам помочь. Здесь нам придётся воспользоваться квантификаторами.

Квантификатор Число повторений Пример Подходящие строки
{n} Ровно n раз Ха{3}ха Хаааха
{m,n} От m до n включительно Ха{2,4}ха Хаа, Хааа, Хааааха
{m,} Не менее m Ха{2,}ха Хааха, Хаааха, Хааааха и т. д.
{,n} Не более n Ха{,3}ха Хха, Хаха, Хааха, Хаааха

Обратите внимание, что квантификатор применяется только к символу, который стоит перед ним.

Некоторые часто используемые конструкции получили в языке регулярных выражений специальные обозначения:

Квантификатор Аналог Значение
? {0,1} Ноль или одно вхождение
* {0,} Ноль или более
+ {1,} Одно или более

Таким образом, с помощью квантификаторов мы можем улучшить наш шаблон для междометий до [Хх][аоеи]+х[аоеи]*, и он сможет распознавать строки “Хааха”, “хееееех” и “Хихии”.

Ленивая квантификация

Предположим, перед нами стоит задача — найти все HTML-теги в строке

<p><b>Tproger</b> — мой <i>любимый</i> сайт о программировании!</p>

Очевидное решение <.*> здесь не сработает — оно найдёт всю строку целиком, т.к. она начинается с тега абзаца и им же заканчивается. То есть содержимым тега будет считаться строка

p><b>Tproger</b> — мой <i>любимый</i> сайт о программировании!</p

Это происходит из-за того, что по умолчанию квантификатор работают по т.н. жадному алгоритму — старается вернуть как можно более длинную строку, соответствующую условию. Решить проблему можно двумя способами. Первый — использовать выражение <[^>]*>, которое запретит считать содержимым тега правую угловую скобку. Второй — объявить квантификатор не жадным, а ленивым. Делается это с помощью добавления справа к квантификатору символа ?. Т.е. для поиска всех тегов выражение обратится в <.*?>.

Ревнивая квантификация

Иногда для увеличения скорости поиска (особенно в тех случаях, когда строка не соответствует регулярному выражению) можно использовать запрет алгоритму возвращаться к предыдущим шагам поиска для того, чтобы найти возможные соответствия для оставшейся части регулярного выражения. Это называется ревнивой квантификацией. Квантификатор делается ревнивым с помощью добавления к нему справа символа +. Ещё одно применение ревнивой квантификации — исключение нежелательных совпадений. Так, паттерну ab*+a в строке “ababa” будут соответствовать только первые три символа, но не символы с третьего по пятый, т.к. символ “a”, который стоит на третьей позиции, уже был использован для первого результата.

Скобочные группы

Для нашего шаблона “смеющегося” междометия осталась самая малость — учесть, что буква “х” может встречаться более одного раза, например, “Хахахахааахахооо”, а может и вовсе заканчиваться на букве “х”. Вероятно, здесь нужно применить квантификатор для группы [аиое]+х, но если мы просто напишем [аиое]х+, то квантификатор + будет относиться только к символу “х”, а не ко всему выражению. Чтобы это исправить, выражение нужно взять в круглые скобки: ([аиое]х)+.

Таким образом, наше выражение превращается в [Хх]([аиое]х?)+ — сначала идёт заглавная или строчная “х”, а потом произвольное ненулевое количество гласных, которые (возможно, но не обязательно) перемежаются одиночными строчными “х”. Однако это выражение решает проблему лишь частично — под это выражение попадут и такие строки, как, например, “хихахех” — кто-то может быть так и смеётся, но допущение весьма сомнительное. Очевидно, мы можем использовать набор из всех гласных лишь единожды, а потом должны как-то опираться на результат первого поиска. Но как?…

Запоминание результата поиска по группе (обратная связь)

Оказывается, результат поиска по скобочной группе записывается в отдельную ячейку памяти, доступ к которой доступен для использования в последующих частях регулярного выражения. Возвращаясь к задаче с поиском HTML-тегов на странице, нам может понадобиться не только найти теги, но и узнать их название. В этом нам может помочь регулярное выражение <(.*?)>.

<p><b>Tproger</b> — мой <i>любимый</i> сайт о программировании!</p>

Результат поиска по всем регулярному выражению: “<p>”, “<b>”, “</b>”, “<i>”, “</i>”, “</p>”.
Результат поиска по первой группе: “p”, “b”, “/b”, “i”, “/i”, “/i”, “/p”.

На результат поиска по группе можно ссылаться с помощью выражения n, где n — цифра от 1 до 9. Например выражению (w)(w)12 соответствуют строки “aaaa”, “abab”, но не соответствует “aabb”.

Если выражение берётся в скобки только для применения к ней квантификатора (не планируется запоминать результат поиска по этой группе), то сразу первой скобки стоит добавить ?:, например (?:[abcd]+w).

С использованием этого механизма мы можем переписать наше выражение к виду [Хх]([аоие])х?(?:1х?)*.

I love or hate regex«>

Перечисление

Чтобы проверить, удовлетворяет ли строка хотя бы одному из шаблонов, можно воспользоваться аналогом булевого оператора OR, который записывается с помощью символа |. Так, под шаблон Анна|Одиночество попадают строки “Анна” и “Одиночество” соответственно. Особенно удобно использовать перечисления внутри скобочных групп. Так, например (?:a|b|c|d) полностью эквивалентно [abcd] (в данном случае второй вариант предпочтительнее в силу производительности и читаемости).

С помощью этого оператора мы сможем добавить к нашему регулярному выражению для поиска междометий возможность распознавать смех вида “Ахахаах” — единственной усмешке, которая начинается с гласной: [Хх]([аоие])х?(?:1х?)*|[Аа]х?(?:ах?)+

Полезные сервисы

Потренироваться и / или проверить своё регулярное выражение на каком-либо тексте без написания кода можно с помощью таких сервисов, как RegExr, Regexpal или Regex101. Последний, вдобавок, приводит краткие пояснения к тому, как регулярка работает.

Разобраться, как работает регулярное выражение, которое попало к вам в руки, можно с помощью сервиса Regexper — он умеет строить понятные диаграмы по регулярному выражению.

RegExp Builder — визуальный конструктор функций JavaScript для работы с регулярными выражениями.

Больше инструментов можно найти в нашей подборке.

Задания для закрепления

Найдите время

Время имеет формат часы:минуты. И часы, и минуты состоят из двух цифр, пример: 09:00. Напишите регулярное выражение для поиска времени в строке: “Завтрак в 09:00”. Учтите, что “37:98” – некорректное время.

Java[^script]

Найдет ли регулярка Java[^script] что-нибудь в строке Java? А в строке JavaScript?

Цвет

Напишите регулярное выражение для поиска HTML-цвета, заданного как #ABCDEF, то есть # и содержит затем 6 шестнадцатеричных символов.

Разобрать арифметическое выражение

Арифметическое выражение состоит из двух чисел и операции между ними, например:

  • 1 + 2
  • 1.2 *3.4
  • -3/ -6
  • -2-2

Список операций: “+”, «-», “*” и “/”.

Также могут присутствовать пробелы вокруг оператора и чисел.

Напишите регулярное выражение, которое найдёт как всё арифметическое действие, так и (через группы) два операнда.

Кроссворды из регулярных выражений

Интересное и полезное времяпрепровождение! Найти такие кроссворды можно в нашей подборке.

tproger.ru

(?:(?:rn)?[ t])*(?:(?:(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|"(?:[^"r\]|\.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|"(?:[^"r\]|\.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*))*@(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*))*|(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|"(?:[^"r\]|\.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)*<(?:(?:rn)?[ t])*(?:@(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*))*(?:,@(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*))*)*:(?:(?:rn)?[ t])*)?(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|"(?:[^"r\]|\.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|"(?:[^"r\]|\.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*))*@(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*))*>(?:(?:rn)?[ t])*)|(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|"(?:[^"r\]|\.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)*:(?:(?:rn)?[ t])*(?:(?:(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|"(?:[^"r\]|\.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|"(?:[^"r\]|\.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*))*@(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*))*|(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|"(?:[^"r\]|\.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)*<(?:(?:rn)?[ t])*(?:@(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*))*(?:,@(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*))*)*:(?:(?:rn)?[ t])*)?(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|"(?:[^"r\]|\.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|"(?:[^"r\]|\.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*))*@(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*))*>(?:(?:rn)?[ t])*)(?:,s*(?:(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|"(?:[^"r\]|\.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|"(?:[^"r\]|\.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*))*@(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*))*|(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|"(?:[^"r\]|\.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)*<(?:(?:rn)?[ t])*(?:@(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*))*(?:,@(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*))*)*:(?:(?:rn)?[ t])*)?(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|"(?:[^"r\]|\.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|"(?:[^"r\]|\.|(?:(?:rn)?[ t]))*"(?:(?:rn)?[ t])*))*@(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*)(?:.(?:(?:rn)?[ t])*(?:[^()<>@,;:\".[] 00-31]+(?:(?:(?:rn)?[ t])+|Z|(?=[["()<>@,;:\".[]]))|[(?:[^[]r\]|\.)*](?:(?:rn)?[ t])*))*>(?:(?:rn)?[ t])*))*)?;s*)

lurkmore.to

Экранирование

Есть специальные символы, которые используются в регулярных выражениях, поэтому их не получится искать. К ним относятся

 )( ] [  ^ $ . | ? * + 

Их следует экранировать, т.е. поставить обратный слеш ().

Для чего же он нужен? Рассмотрим простой пример. У нас есть строка с несколькими предложениями, в которых нам необходимо найти точки. Если вы попробуете это сделать, то будут выделены все символы. Дело в том, что точка является специальным метасимволом, которая заменяет любой символ в регулярном выражении, кроме переноса строки (см. ниже).

Нам следует указать, что точка в нашем случае должна быть не метасимволом, а обычным символом-точкой (.). Экранируя любой метасимвол, мы превращаем его в обычный символ. Это относится и к самому обратному слешу, для экранирования используем \.

Метасимвол точка

Точка заменяет любой символ в регулярном выражении. Если задать точку в регулярном выражении, то будут выделены все символы: буквы, цифры, пробел, точка, запятая и т.д. При этом точка совпадает с одним символом, но благодаря модификатору g поиск не ограничивается первым совпадением и продолжается дальше.

Создайте пример из трёх строк. Если мы добавим квантификатор + после точки (.+), то тем самым зададим поиск совпадающих символов от одного до бесконечности.

Обратите внимание, что регулярное выражение сообщит, что найдено три совпадения (по числу строк), а не количество всех символов, как это было бы без знака плюс.

Поскольку точка не совпадает с символом перевода строки, шаблон найдет совпадение до конца строки.

Мы знаем, что можно экранировать метасимвол точки, чтобы найти обычную точку.

Есть и другой способ — поместить точку в символьный класс, где она рассматривается как обычный символ: [.]+.

Использовать метасимвол точки полезно, когда есть строка с динамической составляющей, которая меняется. http://example.com/pictures/123/

Тогда для строки /pictures/123/, где числа 123 могут меняться, применим паттерн:

 /pictures/.../ 

Мы экранировали слеши, ищем слово pictures, а также любые три символа (обязательно) после этого слова и слеша.

Наборы символов [Квадратные скобки]

Наборы символы позволяют задать определенные ограничения или диапазон. Например, если мы знаем, что будут выводиться только три цифры, то не обязательно использовать три точки, а можно сузить поиск. Для этого используются квадратные скобки, в которых указывается набор символов. Причем ищется только один символ.

Такой пример /pictures/[0-9]/ будет находить строку /pictures/1/ (с одним символом), но не найдет /pictures/123/

Можно указать буквы [a-z] — любой символ алфавита.

Символ ^ означает НЕ — [^ae]

Можно указывать не диапазон, а просто указать нужные символы. Например, [19] (напоминаю, только один символ)

Тогда /pictures/[19]/ найдет варианты /pictures/1/ и /pictures/9/

Есть готовые сокращения для диапазонов

 9 [0-9] цифры D [^d] не цифры s [fnrtv] пробельный символ S [^s] не пробельный символ w [da-zA-Z_] буквенный символ W [^w] не буквенный символ 

Позиция

Если мы хотим найти какой-то конкретный текст, который заканчивается с определенным набором символов, то используется символ $

 Рыжик - это кот. Рыжик - это кот кот по имени Рыжик. 

Тогда выражение кот$ найдет слово только во второй строке. В первой в конце есть точка. В третьей слово начинается, а не заканчивается.

Для поиска строк, которые начинаются на определенное слово используется символ ^. Выражение ^кот найдет слово в третьей строке.

Символ b определяет границу слова, B — не границу слова.

Например, выражение [A-Z] будет находить все заглавные буквы. В том числе по два символа в словах TextView, StatusBar, EditText

Если использовать b[A-Z] то ищутся символы, которые является границей слова. Т.е. будет находить первые заглавные буквы в указанных словах. Соответственно, B[A-Z] наоборот найдет вторые заглавные буквы в этих словах.

Последовательности {Фигурные скобки}

Последовательности задаются фигурными скобками.

Если использовать [A-Z] то найдутся большие заглавные буквы, но один раз. А выражение [A-Z]{1,4} указывает, что нужно показать все повторяющиеся символы от 1 до 4 раз. Можно указать точное значение [A-Z]{3} — найдет слова, где идут именно три заглавные буквы подряд.

До четырех символов [A-Z]{,4}
От четырех символов [A-Z]{4,}

Существует сокращения для них *, +, ?

* — {0,} ноль или более символов
+ — {1,} один или более символов
? — {0,1} ноль или один символ

^.*слово$ — такое выражение найдет целую строку, которое заканчивается на слово.

Перебор

TExT|TEXT — найдет два варианта слова, которые написаны в разных регистрах. | — это или. Как вариант TE(x|X)T — третий символ мы определили в двух вариантах.

Читать регулярные выражения

 ([0-9]+)s.*s(dddd)$ 

В круглых скобках идет набор символов. В квадратных скобках идет набор цифр от 0 до 9, который может повториться один раз. Дальше пробел, бесконечное количество символов. Потом снова пробел. Потом идут четыре цифры подряд, которые обязательно являются концом строки. Например.

 044 - 1234 asdf 123 asdf 1234  ^[tT]eled$ 

Крышка — начало строки. Далее маленькая или большая буква T. Дальше три литерала. В конце строки должна быть цифра. Пример.

 Tele2 tele1 
 ([mM]y name is|I am)s[Mm]ykhailo [Pp]oliarush 

Разные вариации

 My name is Mykhailo Poliaruhs I am mykailo Poliaruhs 

Задачи

Телефонный номер 066.225-23-23

Три цифры, точка обязательно, три цифры, тире, две цифры, тире, две цифры.

 [0-9]{3}.(d{2,3}|-)* 

Как вариант, можно было написать

 d{3}.d{3}-d{2}-d{2} 

parse http: http://host.com/parameters

 [htps]+://w{2,}.w+/w+ 

parse email

 email@gmail.com w+@w+.w+ 

html tag

 <a> <[^<]+?> 

hexidecimal color #aabbcc

 #?[0-9A-Fa-f]{6} 

Применение

UNIX — найти запущенные процессы из папки bin.
Найти все email в тексте

Notepad++ (47.40)

Java (54.35)

developer.alexanderklimov.ru

Что такое регулярные выражения

Регулярные выражения (regular expressions, RegExp) — наборы символов, применяемых для поиска текстовых строк, соответствующих требуемым условиям. Результат применения регулярного выражения — подмножество данных, отобранное согласно логике, заложенной в выражении. Регулярные выражения применяются в любых задачах по поиску в множестве данных, для которых нужно получать выжимку по определенным правилам.

Синтаксис регулярных выражений

Большинство символов в регулярных выражениях представляют сами себя, за исключением группы специальных символов «[ ] / ^ $ . | ? * + ( ) { }». Если эти символы нужно представить в качестве символов текста, их следует экранировать обратной косой чертой «».

Если эти спецсимволы встречаются без обратной косой черты, значит у них особенные значения в регулярных выражениях:

  • «^» — каретка, циркумфлекс или просто галочка. Начало строки;
  • «$» — знак доллара. Конец строки;
  • «.» — точка. Любой символ;
  • «*» – знак умножения, звездочка. Любое количество предыдущих символов;
  • «+» – плюс. 1 или более предыдущих символов;
  • «?» – вопросительный знак. 0 или 1 предыдущих символов;
  • «( )» – круглые скобки. Группировка конструкций;
  • «|» – вертикальная линия. Оператор «ИЛИ»;
  • «[ ]» – квадратные скобки. Любой из перечисленных символов, диапазон. Если первый символ в этой конструкции – «^», то массив работает наоборот – проверяемый символ не должен совпадать с тем, что перечислено в скобках;
  • «{ }» – фигурные скобки. Повторение символа несколько раз;
  • «» – обратный слеш. Экранирование служебных символов.

Также существуют специальные метасимволы, ими можно заменить некоторые готовые конструкции:

  • b — обозначает не символ, а границу между символами;
  • d — цифровой символ;
  • D — нецифровой символ;
  • s — пробельный символ;
  • S — непробельный символ;
  • w — буквенный или цифровой символ или знак подчеркивания;
  • W — любой символ, кроме буквенного или цифрового символа или знака подчеркивания.

Пять способов протестировать свои знания о регулярных выражениях

При изучении регулярных выражений очень важна практика. Чем больше практикуешься, тем быстрее начинаешь строить нужные конструкции и решать поставленные задачи.

1. Изучаем регулярные выражения в текстовом редакторе

Почти всем новичкам я сразу рекомендую ставить текстовый редактор NotePad++ и начинать тренироваться в нём. Почему именно в этом текстовом редакторе:

  • в большинстве случаев спецсимволы не нужно экранировать;
  • Notepad++ сохраняет конструкции предыдущих запросов;
  • функция «Пометки» наглядно показывает результат поиска по заданной конструкции и позволяет быстро внести правки:

функция «Пометки» наглядно показывает результат поиска по заданной конструкции и позволяет быстро внести правки

2. Проверяем знания регулярных выражений в Regex

Онлайн-сервис regex101.com позволяет ввести набор данных и регулярное выражение. После этого в наборе данных подсветятся строки, соответствующие выражению. В специальном окне Explanation регулярное выражение разбирается по частям:

В специальном окне Explanation регулярное выражение разбирается по частям

Давайте потренируемся: задача — подсветить всю строку полностью. Нужно поставить галочку напротив «multi line».

Нужно поставить галочку напротив «multi line»

Тестовые данные:

https://www.site.ua/  www.site.com/search?q=widget+thinger  http://www.site.com/page1/page2/page3/  http://www.site.com/index.php  https://www.site.com/products/100.php  http://www.site.us/products/101.php  http://www.site.com/products/102.php  http://www.site.ua/duals/index.html  http://www.site.com/ourteam/index.php  https://www.site.com/  http://site.com/profile  http://www.site.ru/ua/index.php  http://www.site.com/ua/producty/100.php  http://www.site.com/ua/producty/101.php  https://www.site.com/ua/producty/102.php  http://1.site.com/search?q=widget  http://www.site.com/search?q=widget+thinger  https://www.site.com/search?q=smidges  http://www.site.com/index/yy.jpg

Регулярные выражения для проверки знаний:

  • выбрать все страницы;
    • (.*) — любое количество любых символов;
  • выбрать все страницы с https;
    • ^https.* — все URL, начинающиеся с https;
  • все страницы на украинском языке;
    • .*/ua/.* — все страницы, в URL которых содержится /ua/. Если использовать просто ua, в выборку попадет http://www.site.com/duals/index.html, это лишнее;
  • все индексные страницы;
    • .*index.(php|html) — аналогично прошлому выражению, нельзя просто использовать index;
  • все карточки товаров (для русской и украинской версий);
    • .*product(s|y).* или .*product[sy].* — оба варианта подходят.

3. Тестируем регулярные выражения с помощью Jsfiddle

Jsfiddle — инструмент для экспериментов с JavaScript. В нем можно проверить условия для запуска функции или демонстрации нужных результатов.

В этом примере видно, как на основании регулярных выражений сначала определяется, является ли нажатый элемент ссылкой на файл .pdf или .jpg. После этого для элементов, которые не являются ссылками на файлы, определяются название и цена товара. Все это выясняется, исходя из текстового содержимого элементов.

4. Проверяем ошибки в регулярных выражениях с помощью Google Analytics

Самый быстрый способ проверить знания о регулярных выражениях в Google Analytics — фильтры в стандартных отчетах. Зайдите в свой аккаунт и в любом отчете, где доступны фильтры, попробуйте отобрать какой-либо набор данных.

5. Нестандартные методы освоения регулярных выражений

Для тех, кто любит интерактив:

  • решаем кроссворды; 
  • многоуровневая задачка.

Жадные и ленивые кванторы

Кванторы в регулярных выражениях позволяют определить часть шаблона, которая должна повторяться несколько раз подряд. «Жадный» квантор старается захватить наибольший кусок текста, который только может. А «ленивая» версия (добавляется символ-модификатор «?») ищет наименьшее из возможных вхождений.

Жадный квантор (*) захватывает все — от первых кавычек до последних:

Жадный квантор

Ленивая версия квантора (*?) ищет наименьшее совпадение, поэтому найдет каждую подстроку по отдельности:

Ленивая версия квантора

Где использовать регулярные выражения

SEO-специалисты прибегают к регулярным выражениям при работе с Google Analytics, Яндекс.Метрикой, RewriteRule в .htaccess, в текстовых редакторах, при работе с краулерами (Netpeak Spider).

Расскажу о нескольких регулярных выражених, которые часто мне помогают.

1. Выделить всё, кроме домена:

.*://|/.*

Использую, когда есть большой список URL-адресов (например, внешних ссылок) и для анализа нужно вычленить только домен. В NotePad++ с помощью функции замены меняю на пустую строку и получаю чистый список доменов:

с помощью функции замены меняю на пустую строку и получаю чистый список доменов

2. Выделить URL заданной вложенности:

.*://site.com/.*?/.*?/.*?/

Здесь конструкция (/.*?/) обозначает один уровень вложенности.

Использую это выражение, когда нужно задать максимально разрешенную вложенность URL при сканировании сайта в Netpeak Spider.

Чтобы просканировать все URL адреса только первого уровня вложенности, в сервисе нужно задать такие настройки:

Чтобы просканировать все URL адреса только первого уровня вложенности, в Netpeak Spider нужно задать следующие настройки

Что еще почитать о регулярных выражениях

  • 8 полезных регэкспов с наглядным разбором;
  • Некоторые ошибки при написании регэкспов;
  • Регулярные выражения, пособие для новичков (первая, вторая часть);
  • Истинное могущество регулярных выражений;
  • Шпаргалка по регулярным выражениям и объяснения к шпаргалке.

Выводы

Регулярные выражения — полезный, мощный и совершенно бесплатный инструмент для обработки строковых данных и упрощения работы в различных сервисах.

Его достаточно сложно освоить, ещё сложнее научиться правильно применять. Взамен этот инструмент существенно облегчит вашу работу и сделает её гораздо эффективнее.

Набросаем любимых регулярных выражений в комментариях?

netpeak.net

Creating a regular expression

You construct a regular expression in one of two ways:

Using a regular expression literal, which consists of a pattern enclosed between slashes, as follows:

var re = /ab+c/; 

Regular expression literals provide compilation of the regular expression when the script is loaded. If the regular expression remains constant, using this can improve performance.

Or calling the constructor function of the RegExp object, as follows:

var re = new RegExp('ab+c'); 

Using the constructor function provides runtime compilation of the regular expression. Use the constructor function when you know the regular expression pattern will be changing, or you don’t know the pattern and are getting it from another source, such as user input.

Writing a regular expression pattern

A regular expression pattern is composed of simple characters, such as /abc/, or a combination of simple and special characters, such as /ab*c/ or /Chapter (d+).d*/. The last example includes parentheses which are used as a memory device. The match made with this part of the pattern is remembered for later use, as described in Using parenthesized substring matches.

Using simple patterns

Simple patterns are constructed of characters for which you want to find a direct match. For example, the pattern /abc/ matches character combinations in strings only when exactly the characters ‘abc’ occur together and in that order. Such a match would succeed in the strings «Hi, do you know your abc’s?» and «The latest airplane designs evolved from slabcraft.» In both cases the match is with the substring ‘abc’. There is no match in the string ‘Grab crab’ because while it contains the substring ‘ab c’, it does not contain the exact substring ‘abc’.

Using special characters

When the search for a match requires something more than a direct match, such as finding one or more b’s, or finding white space, you can include special characters in the pattern. For example, to match a single ‘a’ followed by zero or more ‘b’s followed by ‘c’, you’d use the pattern /ab*c/: the * after ‘b’ means «0 or more occurrences of the preceding item.» In the string «cbbabbbbcdebc,» the pattern matches the substring ‘abbbbc’.

The following pages provide a complete list and description of the special characters that can be used in regular expressions.

Assertions
Indicate in some way that a match is possible. Assertions include look-ahead, look-behind, and conditional expressions.
Boundaries
Indicate the beginnings and endings of lines and words.
Character Classes
Distinguish kinds of characters such as, for example, distinguishing between letters and digits.
Groups and Ranges
Indicate groups and ranges of expression characters.
Quantifiers
Indicate numbers of characters or expressions to match.
Unicode Properties
Distinguish based on unicode character properties such as, for example, upper and lower case letters, math symbols, and punctuation.

Escaping

If you need to use any of the special characters literally (actually searching for a ‘*’, for instance), you must escape it by putting a backslash in front of it. For instance, to search for ‘a’ followed by ‘*’ followed by ‘b’, you’d use /a*b/—the backslash «escapes» the ‘*’, making it literal instead of special.

Similarly, if you’re writing a regular expression literal and need to match a slash (‘/’), you need to escape that (otherwise, it terminates the pattern). For instance, to search for the string «/example/» followed by one or more alphabetic characters, you’d use //example/[a-z]+/i—the backslashes before each slash make them literal.

To match a literal backslash, you need to escape the backslash. For instance, to match the string «C:» where ‘C’ can be any letter, you’d use /[A-Z]:\/—the first backslash escapes the one after it, so the expression searches for a single literal backslash.

If using the RegExp constructor with a string literal, remember that the backslash is an escape in string literals, so to use it in the regular expression, you need to escape it at the string literal level. /a*b/ and new RegExp("a\*b") create the same expression, which searches for ‘a’ followed by a literal ‘*’ followed by ‘b’.

If escape strings are not already part of your pattern you can add them using String.replace:

function escapeRegExp(string) {  return string.replace(/[.*+?^${}()|[]\]/g, '\$&'); // $& means the whole matched string } 

The g after the regular expression is an option or flag that performs a global search, looking in the whole string and returning all matches. It is explained in detail below in Advanced Searching With Flags.

Using parentheses

Parentheses around any part of the regular expression pattern causes that part of the matched substring to be remembered. Once remembered, the substring can be recalled for other use, as described in Using Parenthesized Substring Matches.

For example, the pattern /Chapter (d+).d*/ illustrates additional escaped and special characters and indicates that part of the pattern should be remembered. It matches precisely the characters ‘Chapter ‘ followed by one or more numeric characters (d means any numeric character and + means 1 or more times), followed by a decimal point (which in itself is a special character; preceding the decimal point with means the pattern must look for the literal character ‘.’), followed by any numeric character 0 or more times (d means numeric character, * means 0 or more times). In addition, parentheses are used to remember the first matched numeric characters.

This pattern is found in «Open Chapter 4.3, paragraph 6» and ‘4’ is remembered. The pattern is not found in «Chapter 3 and 4», because that string does not have a period after the ‘3’.

To match a substring without causing the matched part to be remembered, within the parentheses preface the pattern with ?:. For example, (?:d+) matches one or more numeric characters but does not remember the matched characters.

Working with regular expressions

Regular expressions are used with the RegExp methods test and exec and with the String methods match, replace, search, and split. These methods are explained in detail in the JavaScript reference.

Methods that use regular expressions
Method Description
exec A RegExp method that executes a search for a match in a string. It returns an array of information or null on a mismatch.
test A RegExp method that tests for a match in a string. It returns true or false.
match A String method that executes a search for a match in a string. It returns an array of information or null on a mismatch.
matchAll A String method that returns an iterator containing all of the matches, including capturing groups.
search A String method that tests for a match in a string. It returns the index of the match, or -1 if the search fails.
replace A String method that executes a search for a match in a string, and replaces the matched substring with a replacement substring.
split A String method that uses a regular expression or a fixed string to break a string into an array of substrings.

When you want to know whether a pattern is found in a string, use the test or search method; for more information (but slower execution) use the exec or match methods. If you use exec or match and if the match succeeds, these methods return an array and update properties of the associated regular expression object and also of the predefined regular expression object, RegExp. If the match fails, the exec method returns null (which coerces to false).

In the following example, the script uses the exec method to find a match in a string.

var myRe = /d(b+)d/g; var myArray = myRe.exec('cdbbdbsbz'); 

If you do not need to access the properties of the regular expression, an alternative way of creating myArray is with this script:

var myArray = /d(b+)d/g.exec('cdbbdbsbz');   // similar to "cdbbdbsbz".match(/d(b+)d/g); however,  // "cdbbdbsbz".match(/d(b+)d/g) outputs Array [ "dbbd" ], while   // /d(b+)d/g.exec('cdbbdbsbz') outputs Array [ 'dbbd', 'bb', index: 1, input: 'cdbbdbsbz' ]. 

(See g different behaviors for further info about the different behaviors.)

If you want to construct the regular expression from a string, yet another alternative is this script:

var myRe = new RegExp('d(b+)d', 'g'); var myArray = myRe.exec('cdbbdbsbz'); 

With these scripts, the match succeeds and returns the array and updates the properties shown in the following table.

Results of regular expression execution.
Object Property or index Description In this example
myArray   The matched string and all remembered substrings. ['dbbd', 'bb', index: 1, input: 'cdbbdbsbz']
index The 0-based index of the match in the input string. 1
input The original string. "cdbbdbsbz"
[0] The last matched characters. "dbbd"
myRe lastIndex The index at which to start the next match. (This property is set only if the regular expression uses the g option, described in Advanced Searching With Flags.) 5
source The text of the pattern. Updated at the time that the regular expression is created, not executed. "d(b+)d"

As shown in the second form of this example, you can use a regular expression created with an object initializer without assigning it to a variable. If you do, however, every occurrence is a new regular expression. For this reason, if you use this form without assigning it to a variable, you cannot subsequently access the properties of that regular expression. For example, assume you have this script:

var myRe = /d(b+)d/g; var myArray = myRe.exec('cdbbdbsbz'); console.log('The value of lastIndex is ' + myRe.lastIndex);  // "The value of lastIndex is 5" 

However, if you have this script:

var myArray = /d(b+)d/g.exec('cdbbdbsbz'); console.log('The value of lastIndex is ' + /d(b+)d/g.lastIndex);  // "The value of lastIndex is 0" 

The occurrences of /d(b+)d/g in the two statements are different regular expression objects and hence have different values for their lastIndex property. If you need to access the properties of a regular expression created with an object initializer, you should first assign it to a variable.

Using parenthesized substring matches

Including parentheses in a regular expression pattern causes the corresponding submatch to be remembered. For example, /a(b)c/ matches the characters ‘abc’ and remembers ‘b’. To recall these parenthesized substring matches, use the Array elements [1], …, [n].

The number of possible parenthesized substrings is unlimited. The returned array holds all that were found. The following examples illustrate how to use parenthesized substring matches.

The following script uses the replace() method to switch the words in the string. For the replacement text, the script uses the $1 and $2 in the replacement to denote the first and second parenthesized substring matches.

var re = /(w+)s(w+)/; var str = 'John Smith'; var newstr = str.replace(re, '$2, $1'); console.log(newstr);  // "Smith, John" 

Advanced searching with flags

Regular expressions have six optional flags that allow for functionality like global and case insensitive searching. These flags can be used separately or together in any order, and are included as part of the regular expression.

Regular expression flags
Flag Description
g Global search.
i Case-insensitive search.
m Multi-line search.
s Allows . to match newline characters.
u «unicode»; treat a pattern as a sequence of unicode code points
y Perform a «sticky» search that matches starting at the current position in the target string. See sticky

To include a flag with the regular expression, use this syntax:

var re = /pattern/flags; 

or

var re = new RegExp('pattern', 'flags'); 

Note that the flags are an integral part of a regular expression. They cannot be added or removed later.

For example, re = /w+s/g creates a regular expression that looks for one or more characters followed by a space, and it looks for this combination throughout the string.

var re = /w+s/g; var str = 'fee fi fo fum'; var myArray = str.match(re); console.log(myArray);  // ["fee ", "fi ", "fo "] 

You could replace the line:

var re = /w+s/g; 

with:

var re = new RegExp('\w+\s', 'g'); 

and get the same result.

The behavior associated with the ‘g‘ flag is different when the .exec() method is used.  (The roles of «class» and «argument» get reversed: In the case of .match(), the string class (or data type) owns the method and the regular expression is just an argument, while in the case of .exec(), it is the regular expression that owns the method, with the string being the argument.  Contrast str.match(re) versus re.exec(str).)  The ‘g‘ flag is used with the .exec() method to get iterative progression.

var xArray; while(xArray = re.exec(str)) console.log(xArray); // produces:  // ["fee ", index: 0, input: "fee fi fo fum"] // ["fi ", index: 4, input: "fee fi fo fum"] // ["fo ", index: 7, input: "fee fi fo fum"]

The m flag is used to specify that a multiline input string should be treated as multiple lines. If the m flag is used, ^ and $ match at the start or end of any line within the input string instead of the start or end of the entire string.

Examples

The following examples show some uses of regular expressions.

Changing the order in an input string

The following example illustrates the formation of regular expressions and the use of string.split() and string.replace(). It cleans a roughly formatted input string containing names (first name last) separated by blanks, tabs and exactly one semicolon. Finally, it reverses the name order (last name first) and sorts the list.

// The name string contains multiple spaces and tabs, // and may have multiple spaces between first and last names. var names = 'Orange Trump ;Fred Barney; Helen Rigby ; Bill Abel ; Chris Hand ';  var output = ['---------- Original Stringn', names + 'n'];  // Prepare two regular expression patterns and array storage. // Split the string into array elements.  // pattern: possible white space then semicolon then possible white space var pattern = /s*;s*/;  // Break the string into pieces separated by the pattern above and // store the pieces in an array called nameList var nameList = names.split(pattern);  // new pattern: one or more characters then spaces then characters. // Use parentheses to "memorize" portions of the pattern. // The memorized portions are referred to later. pattern = /(w+)s+(w+)/;  // Below is the new array for holding names being processed. var bySurnameList = [];  // Display the name array and populate the new array // with comma-separated names, last first. // // The replace method removes anything matching the pattern // and replaces it with the memorized string—the second memorized portion // followed by a comma, a space and the first memorized portion. // // The variables $1 and $2 refer to the portions // memorized while matching the pattern.  output.push('---------- After Split by Regular Expression');  var i, len; for (i = 0, len = nameList.length; i < len; i++) {  output.push(nameList[i]);  bySurnameList[i] = nameList[i].replace(pattern, '$2, $1'); }  // Display the new array. output.push('---------- Names Reversed'); for (i = 0, len = bySurnameList.length; i < len; i++) {  output.push(bySurnameList[i]); }  // Sort by last name, then display the sorted array. bySurnameList.sort(); output.push('---------- Sorted'); for (i = 0, len = bySurnameList.length; i < len; i++) {  output.push(bySurnameList[i]); }  output.push('---------- End');  console.log(output.join('n')); 

Using special characters to verify input

In the following example, the user is expected to enter a phone number. When the user presses the «Check» button, the script checks the validity of the number. If the number is valid (matches the character sequence specified by the regular expression), the script shows a message thanking the user and confirming the number. If the number is invalid, the script informs the user that the phone number is not valid.

Within non-capturing parentheses (?: , the regular expression looks for three numeric characters d{3} OR | a left parenthesis ( followed by three digits d{3}, followed by a close parenthesis ), (end non-capturing parenthesis )), followed by one dash, forward slash, or decimal point and when found, remember the character ([-/.]), followed by three digits d{3}, followed by the remembered match of a dash, forward slash, or decimal point 1, followed by four digits d{4}.

The Change event activated when the user presses Enter sets the value of RegExp.input.

<!DOCTYPE html> <html>   <head>   <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">   <meta http-equiv="Content-Script-Type" content="text/javascript">   <script type="text/javascript">   var re = /(?:d{3}|(d{3}))([-/.])d{3}1d{4}/;   function testInfo(phoneInput) {   var OK = re.exec(phoneInput.value);   if (!OK)   window.alert(phoneInput.value + ' isn't a phone number with area code!');   else  window.alert('Thanks, your phone number is ' + OK[0]);   }   </script>   </head>   <body>   <p>Enter your phone number (with area code) and then click "Check".  <br>The expected format is like ###-###-####.</p>  <form action="#">   <input id="phone"><button onclick="testInfo(document.getElementById('phone'));">Check</button>  </form>   </body>  </html> 

developer.mozilla.org


You May Also Like

About the Author: admind

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.

Adblock
detector