Регулярные выражения. Разбор INI файлы. Альтернативы, группировка и ссылки

Класс RegExp в JavaScript представляет собой регулярные выражения – объект, описывающий символьный шаблон. Объекты RegExp , как правило, создаются с помощью специального синтаксиса литералов, представленного ниже, но так же могут быть созданы посредством конструктора RegExp().

Синтаксис // с помощью специального синтаксиса литералов var regex = /pattern /flags ; // с помощью конструктора var regex = new RegExp("pattern ", "flags "); var regex = new RegExp(/pattern /, "flags ");

Значения параметров:

Флаги регулярных выражений Флаг Описание
g Позволяет найти все совпадения, а не останавливаться после первого совпадения (global match flag ).
i Позволяет выполнить сопоставление без учета регистра (ignore case flag ).
m Сопоставление производится по нескольким строкам. Обработка начальных и конечных символов (^ и $) производится по нескольким строкам, то есть сопоставление происходит с началом или концом каждой строки (разделители \n или \r), а не только с началом, или концом всей строки (multiline flag ).
u Шаблон будет расценен как последовательность кодовых точек Юникода (unicode flag ).
y Сопоставление происходит по индексу на который указывает свойство lastIndex этого регулярного выражения, при этом сопоставление не производиться по более позднему, или раннему индексу (sticky flag ).
Наборы символов Метасимволы Символ Описание
. Позволяет найти один символ, кроме символа новой строки, или символа конца строки (\n, \r, \u2028 или \u2029).
\d Позволяет найти символ цифры в базовом латинском алфавите. Эквивалентин использованию набору символов .
\D Позволяет найти любой символ, который не является цифрой в базовом латинском алфавите. Эквивалентен набору символов [^0-9].
\s Позволяет найти одиночный пробельный символ. Под пробельным символом понимается пробел, табуляция, перевод страницы, перевод строки и другие пробельные символы Юникода. Эквивалентен набору символов [\f\n\r\t\v​\u00a0\u1680​\u180e\u2000​\u2001\u2002​\u2003\u2004​\u2005\u2006​\u2007\u2008​\u2009\u200a​\u2028\u2029​​\u202f\u205f​\u3000].
\S Позволяет найти одиночный символ, который не является пробельным. Под пробельным символом понимается пробел, табуляция, перевод страницы, перевод строки и другие пробельные символы Юникода. Эквивалентен набору символов [^ \f\n\r\t\v​\u00a0\u1680​\u180e\u2000​\u2001\u2002​\u2003\u2004​\u2005\u2006​\u2007\u2008​\u2009\u200a​\u2028\u2029​​\u202f\u205f​\u3000].
[\b] Позволяет найти символ backspace (специальный символ \b, U+0008).
\0 Позволяет найти символ 0 (ноль).
\n Позволяет найти символ новой строки.
\f Позволяет найти символ перевода страницы.
\r Позволяет найти символ возврата каретки.
\t Позволяет найти символ горизонтальной табуляции.
\v Позволяет найти символ вертикальной табуляции.
\w Позволяет найти любой буквенно-цифровой символ базового латинского алфавита, включая подчеркивание. Эквивалентен набору символов .
\W Позволяет найти любой символ, который не является символом из базового латинского алфавита. Эквивалентен набору символов [^a-Za-z0-9_].
\cX Позволяет найти контрольный символ в строке. Где X - буква от A до Z. Например, /\cM/ обозначает символ Ctrl-M.
\xhh Позволяет найти символ, используя шестнадцатеричное значение (hh - двухзначное шестнадцатеричное значение).
\uhhhh Позволяет найти символ, используя кодировку UTF-16 (hhhh - четырехзначное шестнадцатеричное значение).
\u{hhhh} или
\u{hhhhh}
Позволяет найти символ со значением Юникода U+hhhh или U+hhhhh (шестнадцатеричное значение). Только когда задан флаг u .
\ Указывает, что следующий символ является специальным и не должен интерпретироваться буквально. Для символов, которые обычно трактуются специальным образом, указывает, что следующий символ не является специальным и должен интерпретироваться буквально.
Ограничения Квантификаторы Символ Описание
n* Сопостовление происходит с любой строкой, содержащей ноль или более вхождений символа n .
n+ Сопостовление происходит с любой строкой, содержащей хотя бы один символ n .
n? Сопостовление происходит с любой строкой с предшествующим элементом n ноль или один раз.
n{x} Соответствует любой строке, содержащей последовательность символов n определенное количество раз x . X
n{x,} x вхождений предшествующего элемента n . X должно быть целым положительным числом.
n{x, y} Соответствует любой строке, содержащей по крайней мере x , но не более, чем с y вхождениями предшествующего элемента n . X и y должны быть целыми положительными числами.
n*?
n+?
n??
n{x}?
n{x,}?
n{x,y}?
Сопостовление происходит по аналогии с квантификаторами *, +, ? и {...}, однако при этом поиск идет минимально возможного сопоставления. По умолчанию используется "жадный" режим, ? в конце квантификатора позволяет задать "нежадный" режим при котором повторение сопоставления происходит минимально возможное количество раз.
x(?=y) Позволяет сопоставить x , только если за x следует y .
x(?!y) Позволяет сопоставить x , только если за x не следует y .
x|y Сопоставление происходит с любой из указанных альтернатив.
Группировка и обратные ссылки Символ Описание
(x) Позволяет найти символ x и запомнить результат сопоставления ("захватывающие скобки"). Сопоставленная подстрока может быть вызвана из элементов результирующего массива ..., [n], или из свойств предопределенного объекта RegExp $1 ..., $9.
(?:x) Позволяет найти символ x , но не запоминать результат сопоставления ("незахватывающие скобки"). Сопоставленная подстрока не может быть вызвана из элементов результирующего массива ..., [n], или из свойств предопределенного объекта RegExp $1 ..., $9.
\n Обратная ссылка на последнюю подстроку, совпадающую с n-ой по счёту в круглых скобках в регулярном выражении (нумерация скобок идет слева направо). n должно быть целым положительным числом.

JavaScript regexp – это тип объекта, который используется для сопоставления последовательности символов в строках.

Создаем первое регулярное выражение

Существует два способа создания регулярного выражения: с использованием литерала регулярного выражения или с помощью конструктора регулярных выражений. Каждый из них представляет один и тот же шаблон: символ «c », за которым следует «a », а затем символ «t ».

// литерал регулярного выражения заключается в слэши (/)
var option1 = /cat/;
// Конструктор регулярнго выражения
var option2 = new RegExp("cat");

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

Метод RegExp.prototype.test()

Помните, я говорил, что регулярные выражения являются объектами? Это означает, что у них есть ряд методов. Самый простой метод – это JavaScript regexp test , который возвращает логическое значение:

True (истина ): строка содержит шаблон регулярного выражения.

False (ложь ): совпадения не найдено.

console.log(/cat/.test(“the cat says meow”));
// верно
console.log(/cat/.test(“the dog says bark”));
// неверно

Памятка по основам регулярных выражений

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

Символы
  • . – (точка ) соответствует любому одиночному символу за исключением переноса строки;
  • *  –  соответствует предыдущему выражению, которое повторяется 0 или более раз;
  • +  –  соответствует предыдущему выражению, которое повторяется 1 или более раз;
  • ? –  предыдущее выражение является необязательным (соответствует 0 или 1 раз );
  • ^ – соответствует началу строки;
  • $ – соответствует концу строки.
Группы символов
  • d –  соответствует любому одиночному цифровому символу.
  • w –  соответствует любому символу (цифре, букве или знаку подчёркивания).
  • [XYZ ]   –  набор символов. Соответствует любому одиночному символу из набора, заданного в скобках. Также можно задавать и диапазоны символов, например, .
  • [XYZ ]+   –  соответствует символу из набора, повторяемого один или более раз.
  • [^A —Z ]   –  внутри набора символов «^ » используется как знак отрицания. В данном примере шаблону соответствует всё, что не является буквами в верхнем регистре.

Флаги :

В JavaScript regexp существует пять необязательных флагов. Они могут использоваться отдельно или вместе, и размещаются после закрывающего слеша. Например: /[A —Z ]/g . Здесь я приведу только два флага.

g –  глобальный поиск.

i   –  поиск, нечувствительный к регистру.

Дополнительные конструкции

(x )   –   захватывающие скобки. Это выражение соответствует x и запоминает это соответствие, поэтому им можно воспользоваться позже.

(?:x )   –  незахватывающие скобки. Выражение соответствует x , но не запоминает это соответствие.

Соответствует x , только если за ним следует y .

Протестируем изученный материал

Сначала протестируем все выше сказанное. Допустим, что мы хотим проверить строку на наличие любых цифр. Для этого можно использовать конструкцию «d ».

console.log(/d/.test("12-34"));
// верно

Приведенный выше код возвращает значение true , если в строке есть хотя бы одна цифра. Что делать, если нужно проверить строку на соответствие формату? Можно использовать несколько символов «d », чтобы определить формат:

console.log(/dd-dd/.test("12-34"));
//верно
console.log(/dd-dd/.test("1234"));
//неверно

Если неважно, как в JavaScript regexp online идут цифры до и после знака «— », можно использовать символ «+ », чтобы показать, что шаблон «d » встречается один или несколько раз:

console.log(/d+-d+/.test("12-34"));
// верно
console.log(/d+-d+/.test("1-234"));
// верно
console.log(/d+-d+/.test("-34"));
// неверно

Для простоты можно использовать скобки, чтобы сгруппировать выражения. Допустим, у нас есть мяуканье кошки, и мы хотим проверить соответствие шаблону «meow » (мяу ):

console.log(/me+(ow)+w/.test("meeeeowowoww"));
// верно

Теперь давайте разберемся.

m => соответствие одной букве ‘m ‘;

e + => соответствие букве «e» один или несколько раз;

(ow) + => соответствие буквам «ow» один или несколько раз;

w => соответствие букве ‘w ’;

‘m’ + ‘eeee’ + ‘owowow’ + ‘w’ .

Когда операторы типа «+ » используются сразу после скобок, они влияют на все содержимое скобок.

Оператор «? ». Он указывает, что предыдущий символ является необязательным. Как вы увидите ниже, оба тестовых примера возвращают значение true , потому что символы «s » помечены как необязательные.

console.log(/cats? says?/i.test("the Cat says meow"));
//верно
console.log(/cats? says?/i.test("the Cats say meow"));
//верно

Если вы захотите найти символ слеша, нужно экранизировать его с помощью обратного слеша. То же самое верно для других символов, которые имеют особое значение, например, вопросительного знака. Вот JavaScript regexp пример того, как их искать:

var slashSearch = ///;
var questionSearch = /?/;

  • d – это то же самое, что и : каждая конструкция соответствует цифровому символу.
  • w – это то же самое, что [A —Za —z 0-9_] : оба выражения соответствуют любому одиночному алфавитно-цифровому символу или подчеркиванию.
Пример: добавляем пробелы в строки, написанные в «верблюжьем » стиле

В этом примере мы очень устали от «верблюжьего » стиля написания и нам нужен способ добавить пробелы между словами. Вот пример:

removeCc("camelCase") // => должен вернуть "camel Case"

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

Это соответствует символу «C » в «camelCase »

Теперь, как добавить пробел перед «C »?

Нам нужно использовать захватывающие скобки! Они позволяют найти соответствие и запомнить его, чтобы использовать позже! Используйте захватывающие скобки, чтобы запомнить найденную заглавную букву:

Получить доступ к захваченному значению позднее можно так:

Выше мы используем $1 для доступа к захваченному значению. Кстати, если бы у нас было два набора захватывающих скобок, мы использовали бы $1 и $2 для ссылки на захваченные значения и аналогично для большего количества захватывающих скобок.

Если вам нужно использовать скобки, но не нужно фиксировать это значение, можно использовать незахватывающие скобки: (?: x ). В этом случае находится соответствие x , но оно не запоминается.

Вернемся к текущей задаче. Как мы реализуем захватывающие скобки? С помощью метода JavaScript regexp replace ! В качестве второго аргумента мы передаем «$1 ». Здесь важно использовать кавычки.

function removeCc(str){
return str.replace(/()/g, "$1");
}


Снова посмотрим на код. Мы захватываем прописную букву, а затем заменяем ее той же самой буквой. Внутри кавычек вставим пробел, за которым следует переменная $1 . В итоге получаем пробел после каждой заглавной буквы.

function removeCc(str){
return str.replace(/()/g, " $1");
}
removeCc("camelCase") // "camel Case"
removeCc("helloWorldItIsMe") // "hello World It Is Me"

Пример: удаляем заглавные буквы

Теперь у нас есть строка с кучей ненужных прописных букв. Вы догадались, как их удалить? Во-первых, нам нужно выбрать все заглавные буквы. Затем используем поиск набора символов с помощью глобального модификатора:

Мы снова будем использовать метод replace , но как в этот раз сделать строчной символ?

function lowerCase(str){
return str.replace(//g, ???);
}


Подсказка : в методе replace () в качестве второго параметра можно указать функцию.

Мы будем использовать стрелочную функцию, чтобы не захватывать значение найденного совпадения. При использовании функции в методе JavaScript regexp replace эта функция будет вызвана после поиска совпадений, и результат функции используется в качестве замещающей строки. Еще лучше, если совпадение является глобальным и найдено несколько совпадений — функция будет вызвана для каждого найденного совпадения.

function lowerCase(str){
return str.replace(//g, (u) => u.toLowerCase());
}
lowerCase("camel Case") // "camel case"
lowerCase("hello World It Is Me") // "hello world it is me"

Пример: преобразуем первую букву в заглавную

capitalize("camel case") // => должен вернуть "Camel case"

Еще раз воспользуемся функцией в методе replace(). Однако на этот раз нам нужно искать только первый символ в строке. Напомним, что для этого используется символ «^ ».

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

console.log(/cat/.test("the cat says meow"));
//верно

При добавлении символа «^ » функция больше не возвращает значение true , поскольку слово «cat » находится не в начале строки.

Синтаксис регулярных выражений является достаточно сложным и его изучение требует серьёзных усилий. Наилучшим руководством по регулярным выражением на сегодняшний день является книга Дж. Фридла "Регулярные выражения", позволяющая, по словам автора, "научиться мыслить регулярными выражениями".

Основные понятия

Регулярное выражение (regular expression) - средство для обработки строк или последовательность символов, определяющая шаблон текста.

Модификатор - предназначен для "инструктирования" регулярного выражения.

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

Регулярное выражение задаётся как обычная переменная, только вместо кавычек используется слэш, например: var reg=/рег_выражение/

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

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

Создаём шаблон var reg=/р/ и воспользуясь методом replace осуществляем задуманное



var reg=/р/

document.write(result)

В результате получим строку - РегуляRные выражения , замена произошла только на первом вхождении буквы "р" с учётом регистра.

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

модификатор "g" - задаёт поиск в строке как "глобальный", т.е. в нашем случае замена произойдет для всех вхождений буквы "р". Теперь шаблон выглядит так: var reg=/р/g , подставив его в наш код


var str="Регулярные выражения"
var reg=/р/g
var result=str.replace(reg, "R")
document.write(result)

получим строку - РегуляRные выRажения .

модификатор "i" - задаёт поиск в строке без учёта регистра, добавив этот модификатор в наш шаблон var reg=/р/gi , после выполнения скрипта получим искомый результат нашей задачи - RегуляRные выRажения .

Специальные символы (метасимволы)

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

  • Метасимволы поиска совпадений.
  • Количественные метасимволы.
  • Метасимволы позиционирования.
Метасимволы поиска совпадений

Значение

Описание

граница слова

задаёт условие, при котором шаблон должен выполняться в начале или конце слова

/\ber/ совпадает с error , не совпадает с hero или с player
/er/ совпдает с player , не совпадает с hero или с error
/\ber\b/ не совпадает с hero или с player или с error , может совпасть только с er

не граница слова

задаёт условие, при котором шаблон не выполняется в начале или конце слова

/\Ber/ совпадает с hero или с player , не совпадает с error
/er\B/ совпадает с error или с player , не совпадает с hero
/\Ber\B/ совпадает с hero , не совпадает с player или с error

цифра от 0 до 9

/\d\d\d\d/ совпадает с любым четырёх значным числом

/\D\D\D\D/ не совпадёт с 2005 или 05.г или №126 и т.д.

одиночный пустой символ

соответствует символу пробела

\over\sbyte\ совпадает только с over byte

одиночный непустой символ

любой один символ за исключением пробела

\over\Sbyte\ совпадает с over-byte или с over_byte , не совпадает с over byte или over--byte

буква, цифра или символ подчёркивания

/A\w/ совпадает с A1 или с AB , не совпадает с A+

не буква, цифра или символ подчёркивания

/A\W/ не совпадает с A1 или с AB , совпадает с A+

любой символ

любые знаки, буквы, цифры и т.д.

/.../ совпадает с любыми тремя символами ABC или !@4 или 1 q

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

задаёт условие, при котором шаблон должен выполняться при любом совпадении символов заключенных в квадратные скобки

/WERTY/ совпадает с QWERTY , с AWERTY

набор не входящих символов

задаёт условие, при котором шаблон не должен выполняться при любом совпадении символов заключенных в квадратные скобки

/[^QA]WERTY/ не совпадает с QWERTY , с AWERTY

Символы, приведенные в таблице "Метасимволы поиска совпадений" не надо путать с последовательностью знаков перехода используемых в строках, таких как \\t - табуляция, \\n - переход на новую строку и т.д.

Количественные метасимволы

Количество совпадений

Ноль и большее количество раз

/Ja*vaScript/ совпадает с JvaScript или с JaavaScript или с JaaavaScript , не совпадает с JovaScript

Ноль или один раз

/Ja?vaScript/ совпадает только с JvaScript или с JavaScript

Один и большее количество раз

/Ja+vaScript/ совпадает с JavaScript или с JaavaScript или с JaaavaScript , не совпадает с JvaScript

точно n раз

/Ja{2}vaScript/ совпадает только с JaavaScript

n или большее количество раз

/Ja{2,}vaScript/ совпадает с JaavaScript или с JaaavaScript , не совпадает с JvaScript или с JavaScript

по крайней мере, n раз, но не более чем m раз

/Ja{2,3}vaScript/ совпадает только с JaavaScript или с JaaavaScript

Каждый символ, приведенный в таблице "Количественные метасимволы" применяется к одному предшествующему символу или метасимволу в регулярном выражении.

Метасимволы позиционирования

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

Некоторые методы для работы с шаблонами

replace - данный метод мы уже использовали в самом начале статьи, он предназначен для поиска образца и замены найденной подстроки на новую подстроку.

exec - данный метод выполняет сопоставление строки с образцом, заданным шаблоном. Если сопоставление с образцом закончилось неудачей, то возвращается значение null . В противном случае результатом является массив подстрок, соответствующих заданному образцу. /*Первый элемент массива будет равен исходной строке удовлетворяющее заданному шаблону*/

например:


var reg=/(\d+).(\d+).(\d+)/
var arr=reg.exec("Я родился 15.09.1980")
document.write("Дата рождения: ", arr, "< br>")
document.write("День рождения: ", arr, "< br>")
document.write("Месяц рождения: ", arr, "< br>")
document.write("Год рождения: ", arr, "< br>")

в результате получим четыре строки:
Дата рождения: 15.09.1980
День рождения: 15
Месяц рождения: 09
Год рождения: 1980

Заключение

В статье отображено далеко не все возможности и прелести регулярных выражений, для более глубокого изучения этого вопроса посоветую изучить объект RegExp. Так же хочу обратить внимание на то, что синтаксис регулярных выражений не чем не отличается как в JavaScript, так и в PHP. К примеру, для проверки правильности ввода e-mail, регулярное выражение, что для JavaScript, что для PHP будет выглядеть одинаково /+@+.{2,3}/i .

Модификаторы

Символ «минус» (-) меред модификатором (за исключением U) создаёт его отрицание.

Спецсимволы Аналог Описание
() подмаска, вложенное выражение
групповой символ
{a,b} количество вхождений от «a» до «b»
| логическое «или», в случае с односимвольными альтернативами используйте
\ экранирование спец символа
. любой сивол, кроме перевода строки
\d десятичная цифра
\D [^\d] любой символ, кроме десятичной цифры
\f конец (разрыв) страницы
\n перевод строки
\pL буква в кодировке UTF-8 при использовании модификатора u
\r возврат каретки
\s [ \t\v\r\n\f] пробельный символ
\S [^\s] любой символ, кроме промельного
\t табуляция
\w любая цифра, буква или знак подчеркивания
\W [^\w] любой символ, кроме цифры, буквы или знака подчеркивания
\v вертикальная табуляция
Спецсимволы внутри символьного классаПозиция внутри строки Пример Соответствие Описание
^ ^a a aa aaa начало строки
$ a$ aaa aaa конец строки
\A \Aa a aa aaa
aaa aaa
начало текста
\z a\z aaa aaa
aaa aaa
конец текста
\b a\b
\ba
aaa aaa
a aa a aa
граница слова, утверждение: предыдущий символ словесный, а следующий - нет, либо наоборот
\B \Ba\B aa a aa a отсутствие границы слова
\G \Ga aaa aaa Предыдущий успешный поиск, поиск остановился на 4-й позиции — там, где не нашлось a
Скачать в PDF , PNG .Якоря

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

Здесь символ ^ обозначает начало строки. Без него шаблон соответствовал бы любой строке, содержащей цифру.

Символьные классы

Символьные классы в регулярных выражениях соответствуют сразу некоторому набору символов. Например, \d соответствует любой цифре от 0 до 9 включительно, \w соответствует буквам и цифрам, а \W — всем символам, кроме букв и цифр. Шаблон, идентифицирующий буквы, цифры и пробел, выглядит так:

POSIX

POSIX — это относительно новое дополнение семейства регулярных выражений. Идея, как и в случае с символьными классами, заключается в использовании сокращений, представляющих некоторую группу символов.

Утверждения

Поначалу практически у всех возникают трудности с пониманием утверждений, однако познакомившись с ними ближе, вы будете использовать их довольно часто. Утверждения предоставляют способ сказать: «я хочу найти в этом документе каждое слово, включающее букву “q”, за которой не следует “werty”».

[^\s]*q(?!werty)[^\s]*

Приведенный выше код начинается с поиска любых символов, кроме пробела ([^\s]*), за которыми следует q . Затем парсер достигает «смотрящего вперед» утверждения. Это автоматически делает предшествующий элемент (символ, группу или символьный класс) условным — он будет соответствовать шаблону, только если утверждение верно. В нашем случае, утверждение является отрицательным (?!), т. е. оно будет верным, если то, что в нем ищется, не будет найдено.

Итак, парсер проверяет несколько следующих символов по предложенному шаблону (werty). Если они найдены, то утверждение ложно, а значит символ q будет «проигнорирован», т. е. не будет соответствовать шаблону. Если же werty не найдено, то утверждение верно, и с q все в порядке. Затем продолжается поиск любых символов, кроме пробела ([^\s]*).

Кванторы

Кванторы позволяют определить часть шаблона, которая должна повторяться несколько раз подряд. Например, если вы хотите выяснить, содержит ли документ строку из от 10 до 20 (включительно) букв «a», то можно использовать этот шаблон:

A{10,20}

По умолчанию кванторы — «жадные». Поэтому квантор + , означающий «один или больше раз», будет соответствовать максимально возможному значению. Иногда это вызывает проблемы, и тогда вы можете сказать квантору перестать быть жадным (стать «ленивым»), используя специальный модификатор. Посмотрите на этот код:

".*"

Этот шаблон соответствует тексту, заключенному в двойные кавычки. Однако, ваша исходная строка может быть вроде этой:

Привет, Мир

Приведенный выше шаблон найдет в этой строке вот такую подстроку:

"helloworld.htm" title="Привет, Мир"

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

".*?"

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

"helloworld.htm" "Привет, Мир"

Экранирование в регулярных выражениях

Регулярные выражения используют некоторые символы для обозначения различных частей шаблона. Однако, возникает проблема, если вам нужно найти один из таких символов в строке, как обычный символ. Точка, к примеру, в регулярном выражении обозначает «любой символ, кроме переноса строки». Если вам нужно найти точку в строке, вы не можете просто использовать « . » в качестве шаблона — это приведет к нахождению практически всего. Итак, вам необходимо сообщить парсеру, что эта точка должна считаться обычной точкой, а не «любым символом». Это делается с помощью знака экранирования.

Знак экранирования, предшествующий символу вроде точки, заставляет парсер игнорировать его функцию и считать обычным символом. Есть несколько символов, требующих такого экранирования в большинстве шаблонов и языков. Вы можете найти их в правом нижнем углу шпаргалки («Мета-символы»).

Шаблон для нахождения точки таков:

\.

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

Спецсимволы экранирования в регулярных выраженияхПодстановка строк

Подстановка строк подробно описана в следующем параграфе «Группы и диапазоны», однако здесь следует упомянуть о существовании «пассивных» групп. Это группы, игнорируемые при подстановке, что очень полезно, если вы хотите использовать в шаблоне условие «или», но не хотите, чтобы эта группа принимала участие в подстановке.

Группы и диапазоны

Группы и диапазоны очень-очень полезны. Вероятно, проще будет начать с диапазонов. Они позволяют указать набор подходящих символов. Например, чтобы проверить, содержит ли строка шестнадцатеричные цифры (от 0 до 9 и от A до F), следует использовать такой диапазон:

Чтобы проверить обратное, используйте отрицательный диапазон, который в нашем случае подходит под любой символ, кроме цифр от 0 до 9 и букв от A до F:

[^A-Fa-f0-9]

Группы наиболее часто применяются, когда в шаблоне необходимо условие «или»; когда нужно сослаться на часть шаблона из другой его части; а также при подстановке строк.

Использовать «или» очень просто: следующий шаблон ищет «ab» или «bc»:

Если в регулярном выражении необходимо сослаться на какую-то из предшествующих групп, следует использовать \n , где вместо n подставить номер нужной группы. Вам может понадобиться шаблон, соответствующий буквам «aaa» или «bbb», за которыми следует число, а затем те же три буквы. Такой шаблон реализуется с помощью групп:

(aaa|bbb)+\1

Первая часть шаблона ищет «aaa» или «bbb», объединяя найденные буквы в группу. За этим следует поиск одной или более цифр (+), и наконец \1 . Последняя часть шаблона ссылается на первую группу и ищет то же самое. Она ищет совпадение с текстом, уже найденным первой частью шаблона, а не соответствующее ему. Таким образом, «aaa123bbb» не будет удовлетворять вышеприведенному шаблону, так как \1 будет искать «aaa» после числа.

Одним из наиболее полезных инструментов в регулярных выражениях является подстановка строк. При замене текста можно сослаться на найденную группу, используя $n . Скажем, вы хотите выделить в тексте все слова «wish» жирным начертанием. Для этого вам следует использовать функцию замены по регулярному выражению, которая может выглядеть так:

Replace(pattern, replacement, subject)

Первым параметром будет примерно такой шаблон (возможно вам понадобятся несколько дополнительных символов для этой конкретной функции):

([^A-Za-z0-9])(wish)([^A-Za-z0-9])

Он найдет любые вхождения слова «wish» вместе с предыдущим и следующим символами, если только это не буквы или цифры. Тогда ваша подстановка может быть такой:

$1$2$3

Ею будет заменена вся найденная по шаблону строка. Мы начинаем замену с первого найденного символа (который не буква и не цифра), отмечая его $1 . Без этого мы бы просто удалили этот символ из текста. То же касается конца подстановки ($3). В середину мы добавили HTML тег для жирного начертания (разумеется, вместо него вы можете использовать CSS или ), выделив им вторую группу, найденную по шаблону ($2).

Регулярное выражение – это объект, описывающий символьный шаблон. Класс RegExp в JavaScript представляет регулярные выражения, а объекты классов String и RegExp определяют методы, использующие регулярные выражения для выполнения поиска по шаблону и операций поиска в тексте с заменой.

Регулярные выражения – это мощное средство для обработки входящих данных. Задача, требующая замены или поиска текста, может быть красиво решена с помощью этого “языка внутри языка”.

Создание

В JavaScript регулярные выражения представлены объектами RegExp. Объекты RegExp могут быть созданы посредством конструктора RegExp(), но чаще они создаются с помощью специального синтаксиса литералов. Cпособы создания:

// Используя литерал регулярного выражения: var re = /ab+c/;

Литералы регулярных выражений вызывают предварительную компиляцию регулярного выражения при анализе скрипта.

// Вызывая функцию конструктор объекта RegExp var re = new RegExp("ab+c");

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

Спецсимволы в регулярном выражении

\ – Для обычных символов – делает их специальными. Например, выражение /s/ ищет просто символ ‘s’. А если поставить \ перед s, то /\s/ уже обозначает пробельный символ.

^ – Обозначает начало входных данных. Если установлен флаг многострочного поиска (“m”), то также сработает при начале новой строки.

$ – Обозначает конец входных данных. Если установлен флаг многострочного поиска, то также сработает в конце строки.

* – Обозначает повторение 0 или более раз. Например, /bo*/ найдет ‘boooo’ в “A ghost booooed” и ‘b’ в “A bird warbled”, но ничего не найдет в “A goat grunted”.

+ – Обозначает повторение 1 или более раз. Эквивалентно {1,}. Например, /a+/ найдет ‘a’ в “candy” и все ‘a’ в “caaaaaaandy”.

? – Обозначает, что элемент может как присутствовать, так и отсутствовать.

. – (Десятичная точка) обозначает любой символ, кроме перевода строки: \n \r \u2028 or \u2029. (можно использовать [\s\S] для поиска любого символа, включая переводы строк).

(x) – Находит x и запоминает. Это называется “запоминающие скобки”. Например, /(foo)/ найдет и запомнит ‘foo’ в “foo bar.” Найденная подстрока хранится в массиве-результате поиска или в предопределенных свойствах объекта RegExp: $1, …, $9.

(?:x) – Находит x, но не запоминает найденное. Это называется “незапоминающие скобки”. Найденная подстрока не сохраняется в массиве результатов и свойствах RegExp. Как и все скобки, объединяют находящееся в них в единый подпаттерн.

x(?=y) – Находит x, только если за x следует y. Например, /Jack(?=Sprat)/ найдет ‘Jack’, только если за ним следует ‘Sprat’. /Jack(?=Sprat|Frost)/ найдет ‘Jack’, только если за ним следует ‘Sprat’ или ‘Frost’. Однако, ни ‘Sprat’ ни ‘Frost’ не войдут в результат поиска.

x(?!y) – Находит x, только если за x не следует y. Например, /\d+(?!\.)/ найдет число, только если за ним не следует десятичная точка. /\d+(?!\.)/.exec(“3.141”) найдет 141, но не 3.141.

x|y – Находит x или y. Например, /green|red/ найдет ‘green’ в “green apple” и ‘red’ в “red apple.”

{n} – Положительное целое число. Находит ровно n повторений предшествующего элемента.

{n,} – Положительное целое число. Находит n и более повторений элемента.

{n,m} – Положительные целые числа. Находят от n до m повторений элемента.

– Набор символов. Находит любой из перечисленных символов. Можно указать промежуток, используя тире. Например, – то же самое, что .

[^xyz] – Любой символ, кроме указанных в наборе. Также можно указать промежуток. Например, [^abc] – то же самое, что [^a-c].

[\b] – Находит символ backspace.

\b – Находит границу слов (латинских).

\B – Обозначает не границу слов. Например, /\w\Bn/ найдет ‘on’ в “noonday”, а /y\B\w/ найдет ‘ye’ в “possibly yesterday.”

\cX – X – буква от A до Z. Обозначает контрольный символ в строке. Например, /\cM/ обозначает символ Ctrl-M.

\d – Находит цифру из любого алфавита.

\D – Найдет нецифровой символ (все алфавиты). [^0-9] – эквивалент для обычных цифр.

\f,\r,\n – Соответствующие спецсимволы form-feed, line-feed, перевод строки.

\s – Найдет любой пробельный символ, включая пробел, табуляцию, переводы строки и другие юникодные пробельные символы.

\S – Найдет любой символ, кроме пробельного.

\t – Символ табуляции.

\v – Символ вертикальной табуляции.

\w – Найдет любой (латинский) словесный символ, включая буквы, цифры и знак подчеркивания. Эквивалентно .

\W – Найдет любой (не латинский) словесный символ. Эквивалентно [^A-Za-z0-9_].

\0 – Найдет символ NUL.

\xhh – Найдет символ с кодом hh (2 шестнадцатиричных цифры).

\uhhhh – Найдет символ с кодом hhhh (4 шестнадцатиричных цифры).

Флаги

Флаги регулярных выражений задают высокоуровневые правила соответствия шаблонам. В отличие от остальной грамматики регулярных выражений, флаги указываются не между символами слэша, а после второго из них. В языке JavaScript поддерживается три флага.

Флаг i указывает, что поиск по шаблону должен быть нечувствителен к регистру символов, а флаг g – что поиск должен быть глобальным, т.е. должны быть найдены все соответствия в строке. Флаг m выполняет поиск по шаблону в многострочном режиме. Если строковое выражение, в котором выполняется поиск, содержит символы перевода строк, то в этом режиме якорные символы ^ и $, помимо того, что они соответствуют началу и концу всего строкового выражения, также соответствуют началу и концу каждой текстовой строки. Флаги могут объединяться в любые комбинации.

Методы класса String

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

Метод search()

Он принимает в качестве аргумента регулярное выражение и возвращает либо позицию первого символа найденной подстроки, либо -1, если соответствие не найдено. Например, следующий вызов вернет 4:

Var result = "JavaScript".search(/script/i); // 4

Если аргумент метода search() не является регулярным выражением, он сначала преобразуется путем передачи конструктору RegExp. Метод search() не поддерживает глобальный поиск и игнорирует флаг g в своем аргументе.

Метод replace()

Он выполняет операцию поиска с заменой. Он принимает в качестве первого аргумента регулярное выражение, а в качестве второго – строку замены. Метод отыскивает в строке, для которой он вызван, соответствие указанному шаблону. Если регулярное выражение содержит флаг g, метод replace() заменяет все найденные совпадения строкой замены. В противном случае он заменяет только первое найденное совпадение.

Метод match()

Он принимает в качестве единственного аргумента регулярное выражение (или преобразует свой аргумент в регулярное выражение, передав его конструктору RegExp()) и возвращает массив, содержащий результаты поиска. Если в регулярном выражении установлен флаг g, метод возвращает массив всех соответствий, присутствующих в строке. Например:

// вернет ["1", "2", "3"] var result = "1 плюс 2 равно 3".match(/\d+/g);

Если регулярное выражение не содержит флаг g, метод match() не выполняет глобальный поиск; он просто ищет первое совпадение. Однако match() возвращает массив, даже когда метод не выполняет глобальный поиск. В этом случае первый элемент массива – это найденная подстрока, а все оставшиеся элементы представляют собой подвыражения регулярного выражения.

Метод split()

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

"123,456,789".split(","); // Вернет ["123","456","789"]

Метод split() может также принимать в качестве аргумента регулярное выражение. Это делает метод более мощным.

Объект RegExp

Конструктор RegExp() принимает один или два строковых аргумента и создает новый объект RegExp. Первый аргумент конструктора – это строка, содержащая тело регулярного выражения, т.е. текст, который должен находиться между символами слэша в литерале регулярного выражения. Второй аргумент RegExp() может отсутствовать. Если он указан, то определяет флаги регулярного выражения. Это должен быть один из символов g, i, m либо комбинация этих символов.

Свойства RegExp

Каждый объект RegExp имеет пять свойств:

  • source – строка, доступная только для чтения, содержащая текст регулярного выражения.
  • global – логическое значение, доступное только для чтения, определяющее наличие флага g в регулярном выражении.
  • ignoreCase i в регулярном выражении.
  • multiline – это логическое значение, доступное только для чтения, определяющее наличие флага m в регулярном выражении.
  • lastIndex – это целое число, доступное для чтения и записи. Для шаблонов с флагом g это свойство содержит номер позиции в строке, с которой должен быть начат следующий поиск.
Методы RegExp

Объекты RegExp определяют два метода, выполняющие поиск по шаблону.

Метод exec()

Метод exec() выполняет регулярное выражение для указанной строки, т.е. ищет совпадение в строке. Если совпадение не найдено, метод возвращает null. Однако если соответствие найдено, он возвращает такой же массив, как массив, возвращаемый методом match() для поиска без флага g .

Нулевой элемент массива содержит строку, соответствующую регулярному выражению, а все последующие элементы – подстроки, соответствующие всем подвыражениям. В отличие от match(), метод exec() возвращает массив, структура которого не зависит от наличия в регулярном выражении флага g .

Когда метод exec() вызывается для того же регулярного выражения второй раз, он начинает поиск с символа, позиция которого указана в свойстве lastIndex. Если exec() не находит соответствия, свойство lastIndex получает значение 0.

Метод test()

Он принимает строку и возвращает true, если строка соответствует регулярному выражению:

Var pattern = /java/i; pattern.test("JavaScript"); // Вернет true

Вызов test() эквивалентен вызову exec(), возвращающему true, если exec() возвращает не null. По этой причине метод test() ведет себя так же, как метод exec() при вызове для глобального регулярного выражения: он начинает искать указанную строку с позиции, заданной свойством lastIndex, и если находит соответствие, устанавливает свойство lastIndex равным номеру позиции символа, непосредственно следующего за найденным соответствием.

Написание шаблона

Шаблон регулярного выражения состоит из обычных символов, например /abc/, или комбинаций обычных и специальных символов, например /ab*c/ или /Chapter (\d+)\.\d*/. Последний пример включает в себя скобки, которые используются как “запоминающий механизм”. Соответствие этой части шаблона запоминается для дальнейшего использования.

Использование простых шаблонов

Простые шаблоны используются для нахождения прямого соответствия в тексте. Например, шаблон /abc/ соответствует комбинации символов в строке только когда символы ‘abc’ встречаются вместе и в том же порядке.