Регулярные выражения js

Квантификаторы — * + ? и {}

abc*       соответствует строке, в которой после ab следует 0 или более символов c -> тестabc+       соответствует строке, в которой после ab следует один или более символов cabc?       соответствует строке, в которой после ab следует 0 или один символ cabc{2}     соответствует строке, в которой после ab следует 2 символа cabc{2,}    соответствует строке, в которой после ab следует 2 или более символов cabc{2,5}   соответствует строке, в которой после ab следует от 2 до 5 символов ca(bc)*     соответствует строке, в которой после ab следует 0 или более последовательностей символов bca(bc){2,5} соответствует строке, в которой после ab следует от 2 до 5 последовательностей символов bc

search()

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

// Синтаксис метода search()// 'проверяемый текст'.search(/шаблон/)// Создание текста для проверкиconst myString = 'The world of code is not full of code.'// Описание шаблонаconst myPattern = /code/// Использование search() для поиска//совпадения строки с шаблоном,//когда search() находит совпадениеmyString.search(myPattern)// -13// Вызов search() прямо на строке,// когда search() не находит совпадений'Another day in the life.'.search(myPattern)// -1

Точка и перенос строки

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

И javascript здесь не исключение.

Попробуем же сделать поиск и замену многострочного вхождения. Скажем, будем заменять на тэг подчёркивания: :

Попробуйте запустить. Заменяет? Как бы не так!

Дело в том, что в javascript мультилайн режим (флаг ) влияет только на символы ^ и $, которые начинают матчиться с началом и концом строки, а не всего текста.

Точка по-прежнему – любой символ, кроме новой строки. В javascript нет флага, который устанавливает мультилайн-режим для точки. Для того, чтобы заматчить совсем что угодно – используйте .

Работающий вариант:

Статичные регэкспы

В некоторых реализациях javascript регэкспы, заданные коротким синтаксисом /…/ — статичны. То есть, такой объект создается один раз в некоторых реализациях JS, например в Firefox. В Chrome все ок.

function f() {
  // при многократных заходах в функцию объект один и тот же
  var re = /lalala/     
}

По стандарту эта возможность разрешена ES3, но запрещена ES5.

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

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

Доступ к символам

Продемонстрируем, как получить доступ к символам и индексам строки How are you?

"How are you?";

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

"How are you?";

Вывод

r

Мы также можем использовать метод charAt(), чтобы вернуть символ, передавая индекс в качестве параметра.

"Howareyou?".charAt(5);

Вывод

r

Также можно использовать indexOf(), чтобы вернуть индекс первого вхождения символа в строке.

"How are you?".indexOf("o");

Вывод

1

Несмотря на то, что символ «o» появляется в строке How are you? дважды, indexOf() вернёт позицию первого вхождения.

lastIndexOf() используется, чтобы найти последнее вхождение.

"How are you?".lastIndexOf("o");

Вывод

9

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

"How are you?".indexOf("are");

Вывод

4

А вот метод slice() вернёт символы между двумя индексами.

"How are you?".slice(8, 11);

Вывод

you

Обратите внимание на то, что 11– это ?, но? не входит в результирующую строку. slice() вернёт всё, что между указанными значениями индекса

Если второй параметр опускается, slice() вернёт всё, начиная от первого параметра до конца строки.

"How are you?".slice(8);

Вывод

you?

Методы charAt() и slice() помогут получить строковые значения на основании индекса. А indexOf() и lastIndexOf() делают противоположное, возвращая индексы на основании переданной им строки.

Содержимое скобок в match

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

Метод , если у регулярного выражения нет флага , ищет первое совпадение и возвращает его в виде массива:

  1. На позиции будет всё совпадение целиком.
  2. На позиции – содержимое первой скобочной группы.
  3. На позиции – содержимое второй скобочной группы.
  4. …и так далее…

Например, мы хотим найти HTML теги и обработать их. Было бы удобно иметь содержимое тега (то, что внутри уголков) в отдельной переменной.

Давайте заключим внутреннее содержимое в круглые скобки: .

Теперь получим как тег целиком , так и его содержимое в виде массива:

Скобки могут быть и вложенными.

Например, при поиске тега в нас может интересовать:

  1. Содержимое тега целиком: .
  2. Название тега: .
  3. Атрибуты тега: .

Заключим их в скобки в шаблоне: .

Вот их номера (слева направо, по открывающей скобке):

В действии:

По нулевому индексу в всегда идёт полное совпадение.

Затем следуют группы, нумеруемые слева направо, по открывающим скобкам. Группа, открывающая скобка которой идёт первой, получает первый индекс в результате – . Там находится всё содержимое тега.

Затем в идёт группа, образованная второй открывающей скобкой – имя тега, далее в будет остальное содержимое тега: .

Соответствие для каждой группы в строке:

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

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

Если применить его к строке из одной буквы , то результат будет такой:

Массив имеет длину , но все скобочные группы пустые.

А теперь более сложная ситуация для строки :

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

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

Регулярное выражение JavaScript (или Regex ) — это последовательность символов, которую мы можем использовать для эффективной работы со строками. Используя этот синтаксис, мы можем:

  • искать текст в строке
  • заменить подстроки в строке
  • извлекать информацию из строки

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

Литеральный синтаксис использует косую черту ( /pattern/) для обертывания шаблона регулярного выражения, тогда как синтаксис конструктора использует кавычки ( «pattern»). В следующем примере демонстрируются оба способа создания регулярного выражения, которое соответствует любой строке, начинающейся с «Mr.».

ВыполСтрока код »
Скрыть результаты

В приведенном выше примере строка Mr. соответствует шаблону RegExp(«^Mr\\.»). Здесь для проверки соответствия строки шаблону используется метод test().

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

Примечание: При использовании синтаксиса конструктора необходимо дважды экранировать специальные символы, что означает соответствие «.» вам нужно писать «\\.»вместо «\.». Если есть только одна обратная косая черта, она будет интерпретирована парсером строк JavaScript как экранирующий символ и будет удалена.

К специальным символам регулярного выражения относятся: . Вам нужно будет использовать обратную косую черту для этих символов всякий раз, когда вы захотите использовать их буквально. Например, если вы хотите сопоставить «?», Вам нужно будет написать . Все остальные символы автоматически принимают их буквальные значения.

Обратные символьные классы

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

«Обратный» означает, что он соответствует всем другим символам, например:

Не цифра: любой символ, кроме , например буква.
Не пробел: любой символ, кроме , например буква.
Любой символ, кроме , то есть не буквы из латиницы, не знак подчёркивания и не цифра. В частности, русские буквы принадлежат этому классу.

Мы уже видели, как сделать чисто цифровой номер из строки вида : найти все цифры и соединить их.

Альтернативный, более короткий путь – найти нецифровые символы и удалить их из строки:

JavaScript

JS Array
concat()
constructor
copyWithin()
entries()
every()
fill()
filter()
find()
findIndex()
forEach()
from()
includes()
indexOf()
isArray()
join()
keys()
length
lastIndexOf()
map()
pop()
prototype
push()
reduce()
reduceRight()
reverse()
shift()
slice()
some()
sort()
splice()
toString()
unshift()
valueOf()

JS Boolean
constructor
prototype
toString()
valueOf()

JS Classes
constructor()
extends
static
super

JS Date
constructor
getDate()
getDay()
getFullYear()
getHours()
getMilliseconds()
getMinutes()
getMonth()
getSeconds()
getTime()
getTimezoneOffset()
getUTCDate()
getUTCDay()
getUTCFullYear()
getUTCHours()
getUTCMilliseconds()
getUTCMinutes()
getUTCMonth()
getUTCSeconds()
now()
parse()
prototype
setDate()
setFullYear()
setHours()
setMilliseconds()
setMinutes()
setMonth()
setSeconds()
setTime()
setUTCDate()
setUTCFullYear()
setUTCHours()
setUTCMilliseconds()
setUTCMinutes()
setUTCMonth()
setUTCSeconds()
toDateString()
toISOString()
toJSON()
toLocaleDateString()
toLocaleTimeString()
toLocaleString()
toString()
toTimeString()
toUTCString()
UTC()
valueOf()

JS Error
name
message

JS Global
decodeURI()
decodeURIComponent()
encodeURI()
encodeURIComponent()
escape()
eval()
Infinity
isFinite()
isNaN()
NaN
Number()
parseFloat()
parseInt()
String()
undefined
unescape()

JS JSON
parse()
stringify()

JS Math
abs()
acos()
acosh()
asin()
asinh()
atan()
atan2()
atanh()
cbrt()
ceil()
clz32()
cos()
cosh()
E
exp()
expm1()
floor()
fround()
LN2
LN10
log()
log10()
log1p()
log2()
LOG2E
LOG10E
max()
min()
PI
pow()
random()
round()
sign()
sin()
sqrt()
SQRT1_2
SQRT2
tan()
tanh()
trunc()

JS Number
constructor
isFinite()
isInteger()
isNaN()
isSafeInteger()
MAX_VALUE
MIN_VALUE
NEGATIVE_INFINITY
NaN
POSITIVE_INFINITY
prototype
toExponential()
toFixed()
toLocaleString()
toPrecision()
toString()
valueOf()

JS OperatorsJS RegExp
constructor
compile()
exec()
g
global
i
ignoreCase
lastIndex
m
multiline
n+
n*
n?
n{X}
n{X,Y}
n{X,}
n$
^n
?=n
?!n
source
test()
toString()

(x|y)
.
\w
\W
\d
\D
\s
\S
\b
\B
\0
\n
\f
\r
\t
\v
\xxx
\xdd
\uxxxx

JS Statements
break
class
continue
debugger
do…while
for
for…in
for…of
function
if…else
return
switch
throw
try…catch
var
while

JS String
charAt()
charCodeAt()
concat()
constructor
endsWith()
fromCharCode()
includes()
indexOf()
lastIndexOf()
length
localeCompare()
match()
prototype
repeat()
replace()
search()
slice()
split()
startsWith()
substr()
substring()
toLocaleLowerCase()
toLocaleUpperCase()
toLowerCase()
toString()
toUpperCase()
trim()
valueOf()

Квантификаторы

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

/* Квантификатор - Значение */* - 0 или более совпадений с предшествующим выражением.+ - 1 или более совпадений с предшествующим выражением.? - Предшествующее выражение необязательно (то есть совпадений 0 или 1).x{n} - "n" должно быть целым положительным числом. Количество вхождений предшествующего выражения "x" равно "n".x{n, } - "n" должно быть целым положительным числом. Количество вхождений предшествующего выражения "x" равно, как минимум, "n".x{n, m} - "n" может быть равно 0 или целому положительному числу. "m" - целое положительное число. Если "m" > "n", количество вхождений предшествующего выражения "x" равно минимум "n" и максимум "m".

Примеры:

// * - 0 или более совпадений с предшествующим выражениемconst myPattern = /bo*k/console.log(myPattern.test('b'))// falseconsole.log(myPattern.test('bk'))// trueconsole.log(myPattern.test('bok'))// true// + - 1 или более совпадений с предшествующим выражениемconst myPattern = /\d+/console.log(myPattern.test('word'))// falseconsole.log(myPattern.test(13))// true// ? - Предшествующее выражение необязательно, совпадений 0 или 1const myPattern = /foo?bar/console.log(myPattern.test('foobar'))// trueconsole.log(myPattern.test('fooobar'))// false// x{n} - Количество вхождений предшествующего выражения "x" равно "n"const myPattern = /bo{2}m/console.log(myPattern.test('bom'))// falseconsole.log(myPattern.test('boom'))// trueconsole.log(myPattern.test('booom'))// false// x{n, } - Количество вхождений предшествующего выражения "x" равно, как минимум, "n"const myPattern = /do{2,}r/console.log(myPattern.test('dor'))// falseconsole.log(myPattern.test('door'))// trueconsole.log(myPattern.test('dooor'))// true// x{n, m} - Количество вхождений предшествующего выражения "x" равно минимум "n" и максимум "m"const myPattern = /zo{1,3}m/console.log(myPattern.test('zom'))// falseconsole.log(myPattern.test('zoom'))// trueconsole.log(myPattern.test('zooom'))// trueconsole.log(myPattern.test('zoooom'))// false

Поиск: str.match

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

Метод для строки возвращает совпадения с регулярным выражением .

У него есть три режима работы:

Если у регулярного выражения есть флаг , то он возвращает массив всех совпадений:

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

Если такого флага нет, то возвращает только первое совпадение в виде массива, в котором по индексу находится совпадение, и есть свойства с дополнительной информацией о нём:

В этом массиве могут быть и другие индексы, кроме , если часть регулярного выражения выделена в скобки. Мы разберём это в главе Скобочные группы.

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

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

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

Экранирование внутри […]

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

В квадратных скобках большинство специальных символов можно использовать без экранирования:

  • Символы не нужно экранировать никогда.
  • Тире не надо экранировать в начале или в конце (где оно не задаёт диапазон).
  • Символ каретки нужно экранировать только в начале (где он означает исключение).
  • Закрывающую квадратную скобку , если нужен именно такой символ, экранировать нужно.

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

Точка внутри квадратных скобок – просто точка. Шаблон будет искать один из символов: точку или запятую.

В приведённом ниже примере регулярное выражение ищет один из символов :

…Впрочем, если вы решите экранировать «на всякий случай», то не будет никакого вреда:

Замена: str.replace

Метод заменяет совпадения с в строке на (все, если есть флаг , иначе только первое).

Например:

В строке замены мы можем использовать специальные комбинации символов для вставки фрагментов совпадения:

Спецсимволы Действие в строке замены
вставляет всё найденное совпадение
вставляет часть строки до совпадения
вставляет часть строки после совпадения
если это 1-2 значное число, вставляет содержимое n-й скобочной группы регулярного выражения, больше об этом в главе Скобочные группы
вставляет содержимое скобочной группы с именем , также изучим в главе Скобочные группы
вставляет символ

Пример с :

Работа с регулярными выражениями

В JavaScript регулярные выражения используются в методах: exec, test, match, search, replace, split.

Методы, которые используют регулярные выражения

exec При совпадении в строке возвращает массив и обновляет regexp.
test Производит тестирование совпадений в строке. Может быть true или false.
match Выполняет поиск совпадений. Возвращает массив, содержащий результаты этого поиска.
search Производит тестирование совпадений в строке. Возвращает позицию первого символа в найденной строке. Если соответствие не найдено, вернет значение -1.
replace Выполняет поиск совпадений в строке. Ищет строку для регулярного выражения и возвращает новую с измененными указанными значениями.
split Выполняет разбиение строки с регулярным выражением в массив по указанному разделителю.

Методы test и search позволяют узнать, есть ли в строке соответствия шаблону регулярного выражения. Для получения более полной информации используют методы exec и match.

Приведем в пример поиск совпадения в строке с использованием метода exec. Скрипт выглядит так:

var myRe = /d(b+)d/g;
var myArray = myRe.exec("btbbndddpe")

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

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

Объект Индекс Описание Пример
myArray Содержимое myArray.
index Индекс совпадения. Как правило, начинается с нуля. 2
input Исходная строка. btbbndddpe
, … Совпадения во вложенных скобках. Количество скобок может быть неограниченно. = bn

= n

Совпавшие символы. tbbn
myRe lastIndex Значение, с которого начинается следующий поиск совпадения. 3
source Текст шаблона. При создании регулярного выражения обновляется, но не меняется при его выполнении. t(b+)(n)
ignoreCase Показывает, активирован ли флаг i — поиск в зависимости от регистра. true
global Показывает, активирован ли флаг g. true
multiline Показывает, активирован ли флаг m. false

Найти все / Заменить все

Эти две задачи решаются в javascript принципиально по-разному.

Начнем с «простого».

Для замены всех вхождений используется метод String#replace.
Он интересен тем, что допускает первый аргумент — регэксп или строку.

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

Попробуйте:

alert("2 ++ 1".replace("+", "*"))

Каков результат? Как, заменился только один плюс, а не два? Да, вот так.

В режиме регулярного выражения плюс придется заэкранировать, но зато заменит все вхождения (при указании флага ):

alert("2 ++ 1".replace(/\+/g, "*"))

Вот такая особенность работы со строкой.

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

Следующий пример произведет операции вычитания:

var str = "count 36 - 26, 18 - 9"
str = str.replace(/(\d+) - (\d+)/g, function(a,b,c) { return b-c })
alert(str)

В javascript нет одного универсального метода для поиска всех совпадений.
Для поиска без запоминания скобочных групп — можно использовать String#match:

var str = "count 36-26, 18-9"
var re =  /(\d+)-(\d+)/g
result = str.match(re)
for(var i=0; i<result.length; i++) alert(result)

Как видите, оно исправно ищет все совпадения (флаг у регулярного выражения обязателен), но при этом не запоминает скобочные группы. Эдакий «облегченный вариант».

В сколько-нибудь сложных задачах важны не только совпадения, но и скобочные группы. Чтобы их найти, предлагается использовать многократный вызов RegExp#exec.

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

var str = "count 36-26, 18-9"
var re =  /(\d+)-(\d+)/g
var res
while ( (res = re.exec(str)) != null) {
  alert("Найдено " + res + ":  ("+ res+") и ("+res+")")
  alert("Дальше ищу с позиции "+re.lastIndex)
}

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

Поиск совпадений: метод exec

Метод возвращает массив и ставит свойства регулярного выражения.
Если совпадений нет, то возвращается null.

Например,

// Найти одну d, за которой следует 1 или более b, за которыми одна d
// Запомнить найденные b и следующую за ними d
// Регистронезависимый поиск
var myRe = /d(b+)(d)/ig;
var myArray = myRe.exec("cdbBdbsbz");

В результате выполнения скрипта будут такие результаты:

Объект Свойство/Индекс Описания Пример
Содержимое .
Индекс совпадения (от 0)
Исходная строка.
Последние совпавшие символы
Совпадения во вложенных скобках, если есть. Число вложенных скобок не ограничено.
Индекс, с которого начинать следующий поиск.
Показывает, что был включен регистронезависимый поиск, флаг «».
Показывает, что был включен флаг «» поиска совпадений.
Показывает, был ли включен флаг многострочного поиска «».
Текст паттерна.

Если в регулярном выражении включен флаг «», Вы можете вызывать метод много раз для поиска последовательных совпадений в той же строке. Когда Вы это делаете, поиск начинается на подстроке , с индекса . Например, вот такой скрипт:

var myRe = /ab*/g;
var str = "abbcdefabh";
while ((myArray = myRe.exec(str)) != null) {
	var msg = "Found " + myArray + ".  ";
	msg += "Next match starts at " + myRe.lastIndex;
	print(msg);
}

Этот скрипт выведет следующий текст:

Found abb. Next match starts at 3
Found ab. Next match starts at 9

В следующем примере функция выполняет поиск по input. Затем делается цикл по массиву, чтобы посмотреть, есть ли другие имена.

Предполагается, что все зарегистрированные имена находятся в массиве А:

var A = ;

function lookup(input)
{
  var firstName = /\w+/i.exec(input);
  if (!firstName)
  {
    print(input + " isn't a name!");
    return;
  }

  var count = 0;
  for (var i = 0; i < A.length; i++)
  {
    if (firstName.toLowerCase() == A.toLowerCase())
      count++;
  }
  var midstring = (count == 1) ? " other has " : " others have ";
  print("Thanks, " + count + midstring + "the same name!")
}

Используем объект регулярного выражения

Создаем объект регулярного выражения

Этот объект описывает шаблон символов. Он используется для сопоставления шаблонов. Есть два способа сконструировать объект регулярного выражения.

Способ 1: используя литерал регулярного выражения, который состоит из шаблона, заключенного в слэши, например:

var reg = /ab+c/;

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

Способ 2: вызывая функцию-конструктор объекта RegExp, например:

var reg = new RegExp("ab+c");

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

Методы объекта регулярного выражения

Давайте познакомимся с несколькими распространенными методами объекта регулярного выражения:

  • compile() (устарел в версии 1.5) – компилирует регулярное выражение;
  • exec() – производит сопоставление в строке. Возвращает первое совпадение;
  • test() – производит сопоставление в строке. Возвращает значение true или false;
  • toString() – возвращает строчное значение регулярного выражения.

Где писать регулярки?

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

Сразу дам ссылку на сайт, чтобы вы могли уже писать вместе со мной https://www.regextester.com/

Коротко о том, как пользоваться сайтом. Сверху, в графе Regular Expression вы пишете само регулярное выражение, а под ним, в графе Test String вы пишете строку, которую вы хотите фильтровать. Если были найдены соответствия между регулярным выражением и текстом, в тексте эти соответствия будут помечены синим цветом, вы их сразу увидите, даже не сомневайтесь.

Основы основ

Для начала нужно понять что в Regex есть специальные символы (например символ начала строки — ), если вы хотите просто найти данный символ, то нужно ввести обратный слеш перед символом для того, чтобы символ не работал как команда.

Для того чтобы найти текст, нужно собственно просто ввести этот текст:

Якори

— символ который обозначает начало строки

— символ который обозначает конец строки

Найдем строки которые начинаются с The Beginning:

Найдем строки, которые заканчиваются на The End:

Найдем строки, которые начинаются и заканчиваются на The Beginning and The End:

Найдем пустые строки:

Квантификаторы

— символ, который указывает на то, что выражение до него должно встретиться 0 или 1 раз

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

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

— скобки с одним аргументом указывают сколько раз выражение до них должно встретиться

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

— скобки объединяют какое-то предложение в выражение. Обычно используется в связке с квантификаторами

Давайте попробуем найти текст, в котором будут искаться все слова, содержащие ext или ex:

Давайте попробуем найти текст, в котором слова будут содержать ext или e:

Найти все размеры одежды (XL, XXL, XXXL):

Найти все слова, у которых есть неограниченное число символов c, после которых идёт haracter:

Найти выражение, в котором слово word повторяется от одного до неограниченного количества раз:

Найти выражение, в котором выражение ch повторяется от 3 до неограниченного количества раз:

Выражение «или»

— символ, который обозначает оператор «или»

— выражение в квадратных скобках ставит или между каждым подвыражением

Найти все слова, в которых есть буквы a,e,c,h,p:

Найти все выражения в которых есть ch или pa:

Escape-последовательности

— отмечает один символ, который является цифрой (digit)\

— отмечает символ, который не является цифрой

— отмечает любой символ (число или букву (или подчёркивание)) (word)

— отмечает любой пробельный символ (space character)

— отмечает любой символ (один)

Выражения в квадратных скобках

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

— один символ от 0 до 9

— любой символ от a до z

— любой символ от A до Z

— любой символ кроме a — z

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

Флаги

Флаги — символы (набор символов), которые отвечают за то, каким именно образом будет происходить поиск.

Форма условия поиска в Regex выглядит вот так:

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

— флаг, который заставляет искать выражения вне зависимости от региста (case insensitive)

Примеры

Применение test()

Метод test() – регулярное выражение объекта RegExp. Он производит поиск строки шаблона, и в зависимости от полученного результата возвращает значение true или false. Следующий JS регулярного выражения пример показывает, как происходит поиск в строке символа “e”:

var patt = /e/;
patt.test("Лучшие в мире вещи – бесплатны!");

Так как здесь в строке имеется “e”, результатом данного кода будет значение true.

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

/e/.test("Лучшие в мире вещи – бесплатны!");

Применение exec()

Он производит поиск в строке по заданному правилу поиска, и возвращает найденный текст. Если совпадений найдено не было, то результатом будет null.

Посмотрим на метод в действии, на примере того же символа “e”:

/e/.exec("Лучшие в мире вещи – бесплатны!");

Так как в строке имеется “e”, результатом данного кода будет .e.

Статические свойства

Ну и напоследок — еще одна совсем оригинальная особенность регулярных выражений.

Вот — одна интересная функция.

Запустите ее один раз, запомните результат — и запустите еще раз.

function rere() {
    var re1 = /0/, re2 = new RegExp('0')
    alert()
    re1.foo = 1
    re2.foo = 1
}
rere()

В зависимости от браузера, результат первого запуска может отличаться от второго. На текущий момент, это так для Firefox, Opera. При этом в Internet Explorer все нормально.

С виду функция создает две локальные переменные и не зависит от каких-то внешних факторов.

Почему же разный результат?

Ответ кроется в стандарте ECMAScript, :

Цитата…

A regular expression literal is an input element that is converted to a RegExp object (section 15.10)
when it is scanned. The object is created before evaluation of the containing program or function begins.
Evaluation of the literal produces a reference to that object; it does not create a new object.

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

В отличие от этого, всегда создает новый объект, поэтому и ведет себя в примере по-другому.

Ещё примеры

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

Регулярное выражение для десятичных дробей (чисел с плавающей точкой):

В действии:

Регулярное выражение для «открывающего HTML-тега без атрибутов», например, или .

  1. Самое простое:

    Это регулярное выражение ищет символ , за которым идут одна или более букв латинского алфавита, а затем .

  2. Улучшенное:

    Здесь регулярное выражение расширено: в соответствие со стандартом, в названии HTML-тега цифра может быть на любой позиции, кроме первой, например .

Регулярное выражение для «открывающего или закрывающего HTML-тега без атрибутов»:

В начало предыдущего шаблона мы добавили необязательный слеш . Этот символ понадобилось заэкранировать, чтобы JavaScript не принял его за конец шаблона.

Чтобы регулярное выражение было точнее, нам часто приходится делать его сложнее

В этих примерах мы видим общее правило: чем точнее регулярное выражение – тем оно длиннее и сложнее.

Например, для HTML-тегов без атрибутов, скорее всего, подошло бы и более простое регулярное выражение: . Но стандарт HTML накладывает более жёсткие ограничения на имя тега, так что более точным будет шаблон .

Подойдёт ли нам или нужно использовать ? А, может быть, нужно ещё его усложнить, добавить атрибуты?

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

Наборы и флаг «u»

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

Например, давайте попробуем найти шаблон в строке :

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

Движок регулярных выражений думает, что – это не два, а четыре символа:

  1. левая половина от ,
  2. правая половина от ,
  3. левая половина от ,
  4. правая половина от .

Мы даже можем вывести их коды:

То есть в нашем примере выше ищется и выводится только левая половина от .

Если добавить флаг , то всё будет в порядке:

Аналогичная ситуация произойдёт при попытке искать диапазон: .

Если мы забудем флаг , то можем нечаянно получить ошибку:

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

При использовании флага шаблон будет работать правильно:

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

В JavaScript регулярные выражения представлены объектом , который является нативным объектом JavaScript, таким как , и так далее. Существует два способа создания нового объекта RegExp: один использует литеральный синтаксис, а другой — конструктор .

Литеральный синтаксис использует косую черту () для переноса шаблона регулярного выражения, тогда как синтаксис конструктора использует кавычки (). В следующем примере демонстрируются оба способа создания регулярного выражения, которое соответствует любой строке, начинающейся с «Mr.».

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

При использовании синтаксиса конструктора необходимо дважды экранировать специальные символы; это означает, что для поиска «.» вам нужно написать вместо . Если есть только один обратный слеш, он будет интерпретирован синтаксическим анализатором строк JavaScript как экранирующий символ и будет удален.

Итого

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

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

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

  • Метод возвращает скобочные группы только без флага .
  • Метод возвращает скобочные группы всегда.

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

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

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

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

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

Adblock
detector