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

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

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

(?:ABC) – Это выражение также производит поиск группы символов, но не сохраняет результат.

\d+(?=ABC) – выражение соответствует символам предшествующим (?=ABC), только если за ним следует “ABC”. Часть “ABC” не будет учитываться при поиске. Часть выражения “\d” приведена всего лишь для примера. На ее месте может быть любое регулярное выражение.

\d+(?!ABC) – выражение соответствует символам предшествующим (?!ABC), только если за ним НЕ следует “ABC”. Часть “ABC” не будет учитываться при поиске. Часть выражения “\d” приведена всего лишь для примера. На ее месте может быть любое регулярное выражение.

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

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

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

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

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

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

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

Для поиска символов определенного вида в регулярных выражениях есть «классы символов». Например ищет одну цифру. Есть и другие классы.

Основные классы

  • – цифры.
  • – не-цифры.
  • – пробельные символы, переводы строки.
  • – всё, кроме \s.
  • – латиница, цифры, подчёркивание ‘_’.
  • – всё, кроме \w.
  • – символ табуляции
  • – символ перевода строки
  •  – точка обозначает любой символ, кроме перевода строки.

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

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

  • – произвольный символ от a до z
  • произвольный символ от B до G в верхнем регистре
  • – то же самое, что и \d, любая цифра от 0 до 9
  •  – любая цифра или буква, можно комбинировать диапазоны
  •  – диапазон «кроме», ищет любые символы, кроме цифр

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

Не экранируем в квадратных скобках

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

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

  • Количество {n} — 5 цифр — одна или больше цифр — от одной до 5 цифр
  • Один или более +, аналог {1,} — одна или более цифр — одна или более букв от a до z
  • Ноль или один ?, аналог {0,1} — найдет color и colour
  • Означает «ноль или более» *, аналог {0,} — найдет «1» и «100» в строке «1 100», символ может повторяться много раз или вообще отсутствовать.

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

Вы можете заключить одну или несколько частей шаблона в скобки — это и будет называться скобочной группой. Основной профит — при использовании методов match, exec, replace — можно вытащить значения в скобках в отдельный элемент массива. И еще, если поставить квантификатор после скобки, то он применится ко всей скобке, а не к одному символу. Еще вы можете использовать вложенные скобки, то есть разбивать большой шаблон на несколько маленьких.

Пример использования вы можете посмотреть выше — в нестандартном применении метода replace().

Простым языком, это «ИЛИ».

— аналог \d  -любая цифра — найдет «imacros» или «js»

Начало строки ^ и конец $

Знак каретки ‘^’ и доллара ‘$’ имеют в регулярном выражении особый смысл. Их называют «якорями» (anchor – англ.).
Каретка совпадает в начале текста, а доллар – в конце. Знак доллара $ используют, чтобы указать, что паттерн должен заканчиваться в конце текста, знак каретки ^ — что паттерн должен начинаться с первого символа строки.

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

В Javascript эти выражения также можно использовать с двумя методами объекта String: search() и replace(). Они нужны для выполнения поиска и замены в тексте.

  • Метод search() — использует выражение для поиска соответствия, и возвращает информацию о расположении соответствия;
  • Метод replace() — возвращает модифицированную строку с замененным шаблоном.

Примеры

Применение регулярного выражения JS для осуществления чувствительного к регистру поиска фразы “w3schools” в строке:

var str = "Visit W3Schools";
var n = str.search(/w3schools/i);

Результатом в n будет 6.

Метод search также принимает строку в качестве аргумента. Аргумент string будет преобразован в регулярное выражение:

Применение string для поиска фразы “W3schools” в строке:

var str = "Visit W3Schools!";
var n = str.search("W3Schools");

Применение чувствительного к регистру регулярного выражения JS для замены «Microsoft» на «W3Schools» в строке:

var str = "Visit Microsoft!";
var res = str.replace(/microsoft/i, "W3Schools");

В результате мы получим: «Visit W3Schools!«.

Метод replace() также принимает строку для поиска:

var str = “Visit Microsoft!”;
var res = str.replace(“Microsoft”, “W3Schools”);

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

В регулярных выражениях могут применяться специальные флаги. Они влияют на поиск.

Флаг Описание
i Осуществляется поиск без привязки к регистру. Найдет соответствия в верхнем и нижнем регистрах (D и d).
g Глобальный поиск. Осуществляется поиск всех совпадений, а не только первого.
m Многострочный поиск. Влияет на символы ^ (поиск совпадений в начале строки) и $ (поиск совпадений в конце строки).
y Поиск по заданной позиции в исходной строке.
u Поддержка Unicode.
s Поиск любого символа, включая перенос строки \n.

Флаги в шаблонах регулярных выражений используются с помощью синтаксисов:

var re = /pattern/flags;

или

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

Флаги указываются после шаблона/паттерна.

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

Эти две задачи решаются в 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)
}

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

Строковые методы, поиск и замена

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

Все методы, кроме replace, можно вызывать как с объектами типа regexp в аргументах, так и со строками, которые автоматом преобразуются в объекты RegExp.

Так что вызовы эквивалентны:

var i = str.search(/\s/)
var i = str.search("\\s")

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

var regText = "\\s"
var i = str.search(new RegExp(regText, "g"))

Возвращает индекс регулярного выражения в строке, или -1.

Если Вы хотите знать, подходит ли строка под регулярное выражение, используйте метод (аналогично RegExp-методы ). Чтобы получить больше информации, используйте более медленный метод (аналогичный методу ).

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

function testinput(re, str){
   if (str.search(re) != -1)
      midstring = " contains ";
   else
      midstring = " does not contain ";
   document.write (str + midstring + re.source);
}

Если в regexp нет флага , то возвращает тот же результат, что .

Если в regexp есть флаг , то возвращает массив со всеми совпадениями.

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

Если Вы хотите получить первый результат — попробуйте r.

В следующем примере используется, чтобы найти «Chapter», за которой следует 1 или более цифр, а затем цифры, разделенные точкой. В регулярном выражении есть флаг , так что регистр будет игнорироваться.

str = "For more information, see Chapter 3.4.5.1";
re = /chapter (\d+(\.\d)*)/i;
found = str.match(re);
alert(found);

Скрипт выдаст массив из совпадений:

  • Chapter 3.4.5.1 — полностью совпавшая строка
  • 3.4.5.1 — первая скобка
  • .1 — внутренняя скобка

Следующий пример демонстрирует использование флагов глобального и регистронезависимого поиска с . Будут найдены все буквы от А до Е и от а до е, каждая — в отдельном элементе массива.

var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
var regexp = //gi;
var matches = str.match(regexp);
document.write(matches);

// matches = 

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

var newString = str.replace(regexp/substr, newSubStr/function)
Объект RegExp. Его вхождения будут заменены на значение, которое вернет параметр номер 2
Строка, которая будет заменена на .
Строка, которая заменяет подстроку из аргумента номер 1.
Функция, которая может быть вызвана для генерации новой подстроки (чтобы подставить ее вместо подстроки, полученной из аргумента 1).

Метод не меняет строку, на которой вызван, а просто возвращает новую, измененную строку.

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

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

var ab = "a b".replace("\\s","..") // = "a b"

Вызов replace оставил строку без изменения, т.к искал не регулярное выражение , а строку «\s».

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

Pattern Inserts
Вставляет «$».
Вставляет найденную подстроку.
Вставляет часть строки, которая предшествует найденному вхождению.
Вставляет часть строки, которая идет после найденного вхождения.
or Где или — десятичные цифры, вставляет подстроку вхождения, запомненную -й вложенной скобкой, если первый аргумент — объект RegExp.

Если Вы указываете вторым параметром функцию, то она выполняется при каждом совпадении.

В функции можно динамически генерировать и возвращать строку подстановки.

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

Например, следующий вызов возвратит XXzzzz — XX , zzzz.

function replacer(str, p1, p2, offset, s)
{
return str + " - " + p1 + " , " + p2;
}
var newString = "XXzzzz".replace(/(X*)(z*)/, replacer)

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

Следующая функция заменяет слова типа на :

function styleHyphenFormat(propertyName)
{
  function upperToHyphenLower(match)
  {
    return '-' + match.toLowerCase();
  }
  return propertyName.replace(//, upperToHyphenLower);
}

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

В JavaScript регулярные выражения используются в методах: 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

Самые простые регулярки

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

Пример регулярки

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

Например, мы можем написать одну букву t, и он найдет все буквы t в тексте

Шутка конечно, это далеко не всё. Например, мы можем написать одну букву t, и он найдет все буквы t в тексте.

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

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

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

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

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

function bbtagit(text) {
  text = text.replace(/\(.*?)\[\/u\]/gim, '<u>$1</u>')
 
  return text
}

var line = "мой\n текст"
alert( bbtagit(line) )

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

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

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

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

function bbtagit(text) {
  text = text.replace(/\(*)\[\/u\]/gim, '<u>$1</u>')
 
  return text
}

var line = "мой\n текст"
alert( bbtagit(line) )

Символьные классы — \d \w \s и .

\d соответствует одному символу, который является цифрой -> тест\w соответствует слову (может состоять из букв, цифр и подчёркивания) -> тест\s соответствует символу пробела (включая табуляцию и прерывание строки). соответствует любому символу -> тест

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

У операторов , и также есть отрицания ― исоответственно.

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

\D соответствует одному символу, который не является цифрой -> тест

Некоторые символы, например , необходимо выделять обратным слешем .

\$\d соответствует строке, в которой после символа $ следует одна цифра -> тест

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

matchAll()

Подобно методу , возвращает все совпадения при использовании флага в шаблоне. Однако работает он по-другому. Метод возвращает объект . Есть несколько способов извлечь из него все совпадения.

Во-первых, можно пройтись по объекту циклом и вернуть или записать все совпадения. Также можно использовать , чтобы создать массив из содержимого объекта, или оператор spread, который даст точно такой же результат, как и .


// Синтаксис метода match()// ‘проверяемый текст’.match(/шаблон/)// Создание текста для проверкиconst myString = ‘The world of code is not full of code.’// Описание шаблонаconst myPattern = /code/g// Обратите внимание, что используется флаг ‘g’// Использование matchAll() для поиска совпадений в текстеconst matches = myString.matchAll(myPattern)// Использование цикла for…of для получения всех совпаденийfor (const match of matches) { console.log(match)}// [// [// ‘code’,// index: 13,// input: ‘The world of code is not full of code.’,// groups: undefined// ],// [// ‘code’,// index: 33,// input: ‘The world of code is not full of code.’,// groups: undefined// ]// ]// Использование Array.from() для получения всех совпаденийconst matches = Array.from(myString.matchAll(myPattern))// [// [// ‘code’,// index: 13,// input: ‘The world of code is not full of code.’,// groups: undefined// ],// [// ‘code’,// index: 33,// input: ‘The world of code is not full of code.’,// groups: undefined// ]// ]// Использование оператора spread для получения всех совпаденийconst matches = // [// [// ‘code’,// index: 13,// input: ‘The world of code is not full of code.’,// groups: undefined// ],// [// ‘code’,// index: 33,// input: ‘The world of code is not full of code.’,// groups: undefined// ]// ]

Как создавать простые шаблоны?

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

// Создание простого шаблона// с использованием литерала регулярного выраженияconst myPattern = /JavaScript/// Проверка строки на совпадения с шаблономmyPattern.test('One of the most popular languages is also JavaScript.')// true// Проверка строки на совпадения с шаблономmyPattern.test('What happens if you combine Java with scripting?')// false

Как создавать сложные шаблоны со специальными символами?

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

Замена: str.replace

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

Например:

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

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

Пример с :

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

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

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

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

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

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

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

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

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

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

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

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

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

Наборы и диапазоны

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

/* Набор или диапазон - Значение */ - любой один из символов в скобках. — любой символ, за исключением символов в скобках. - любой символ в диапазоне от "a" до "z". - любой символ не из диапазона от "a" до "z".(x) - "x", значение запоминается для дальнейшего использования.(?<name>x) - создание именованной скобочной группы, к которой можно обратиться по указанному имени.(?:x) - "x", значение не запоминается, поэтому совпадение невозможно извлечь из итогового массива элементов.

Примеры:

//  - Любой один из символов в скобках.const myPattern = //console.log(myPattern.test('aei'))// true (есть a, e, i)console.log(myPattern.test('form'))// false (нет a, e или i)//  - Любой символ, за исключением символов в скобках.const myPattern = //console.log(myPattern.test('aei'))// false (нет других символов, кроме a, e и i)console.log(myPattern.test('form'))// true (есть другие символы, кроме a, e и i)//  - Любой символ в диапазоне от "a" до "z".const myPattern = //console.log(myPattern.test('bcd'))// true (есть символы в диапазоне от 'b' до 'g')console.log(myPattern.test('jklm'))// false (нет символов в диапазоне от 'b' до 'g')//  - Любой символ не из диапазона от "a" до "z".const myPattern = //console.log(myPattern.test('bcd'))// false (нет других символов, кроме входящих в диапазон от 'b' до 'g')console.log(myPattern.test('jklm'))// true (есть другие символы, кроме входящих в диапазон от 'b' до 'g')// (x) - "x", значение запоминается для дальнейшего использования.const myPattern = /(na)da\1/console.log(myPattern.test('nadana'))// true - \1 запоминает и использует совпадение 'na' из первого выражения в скобках.console.log(myPattern.test('nada'))// false// (?<name>x) - Создание именованной скобочной группы, к которой можно обратиться по указанному имени.const myPattern = /(?<foo>is)/console.log(myPattern.test('Work is created.'))// trueconsole.log(myPattern.test('Just a text'))// false// (?:x) - "x", значение не запоминается.const myPattern = /(?:war)/console.log(myPattern.test('warsawwar'))// trueconsole.log(myPattern.test('arsaw'))// false

Итого

Существуют следующие символьные классы:

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

…Но это не всё!

В кодировке Юникод, которую JavaScript использует для строк, каждому символу соответствует ряд свойств, например – какого языка это буква (если буква), является ли символ знаком пунктуации, и т.п.

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

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

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

Adblock
detector