Содержание
В этой главе мы рассмотрим все детали методов для работы с регулярными выражениями.
str.match(regexp)
Метод str.match(regexp) ищет совпадения с regexp в строке str .
У него есть три режима работы:
Если у регулярного выражения нет флага g , то он возвращает первое совпадение в виде массива со скобочными группами и свойствами index (позиция совпадения), input (строка поиска, равна str ):
Если у регулярного выражения есть флаг g , то он возвращает массив всех совпадений, без скобочных групп и других деталей.
Если совпадений нет, то, вне зависимости от наличия флага g , возвращается null .
Это очень важный нюанс. При отсутствии совпадений возвращается не пустой массив, а именно null . Если об этом забыть, можно легко допустить ошибку, например:
Если хочется, чтобы результатом всегда был массив, можно написать так:
str.matchAll(regexp)
Метод str.matchAll(regexp) – «новый, улучшенный» вариант метода str.match .
Он используется, в первую очередь, для поиска всех совпадений вместе со скобочными группами.
У него 3 отличия от match :
- Он возвращает не массив, а перебираемый объект с результатами, обычный массив можно сделать при помощи Array.from .
- Каждое совпадение возвращается в виде массива со скобочными группами (как str.match без флага g ).
- Если совпадений нет, то возвращается не null , а пустой перебираемый объект.
При переборе результатов matchAll в цикле for..of вызов Array.from , разумеется, не нужен.
str.split(regexp|substr, limit)
Разбивает строку в массив по разделителю – регулярному выражению regexp или подстроке substr.
Обычно мы используем метод split со строками, вот так:
Но мы можем разделить по регулярному выражению аналогичным образом:
str.search(regexp)
Метод str.search(regexp) возвращает позицию первого совпадения с regexp в строке str или -1 , если совпадения нет.
Важное ограничение: str.search умеет возвращать только позицию первого совпадения.
Если нужны позиции других совпадений, то следует использовать другой метод, например, найти их все при помощи str.matchAll(regexp) .
str.replace(str|regexp, str|func)
Это универсальный метод поиска-и-замены, один из самых полезных. Этакий швейцарский армейский нож для поиска и замены в строке.
Мы можем использовать его и без регулярных выражений, для поиска-и-замены подстроки:
Хотя есть подводный камень.
Когда первый аргумент replace является строкой, он заменяет только первое совпадение.
Вы можете видеть это в приведённом выше примере: только первый "-" заменяется на ":" .
Чтобы найти все дефисы, нам нужно использовать не строку "-" , а регулярное выражение /-/g с обязательным флагом g :
Второй аргумент – строка замены. Мы можем использовать специальные символы в нем:
Спецсимволы | Действие в строке замены |
---|---|
$$ | вставляет "$" |
$& | вставляет всё найденное совпадение |
$` | вставляет часть строки до совпадения |
$’ | вставляет часть строки после совпадения |
$n | если n это 1-2 значное число, то вставляет содержимое n-й скобки |
$ | вставляет содержимое скобки с указанным именем |
Для ситуаций, которые требуют «умных» замен, вторым аргументом может быть функция.
Она будет вызываться для каждого совпадения, и её результат будет вставлен в качестве замены.
Функция вызывается с аргументами func(match, p1, p2, . pn, offset, input, groups) :
- match – найденное совпадение,
- p1, p2, . pn – содержимое скобок (см. главу Скобочные группы).
- offset – позиция, на которой найдено совпадение,
- input – исходная строка,
- groups – объект с содержимым именованных скобок (см. главу Скобочные группы).
Если скобок в регулярном выражении нет, то будет только 3 аргумента: func(match, offset, input) .
Например, переведём выбранные совпадения в верхний регистр:
Заменим каждое совпадение на его позицию в строке:
В примере ниже двое скобок, поэтому функция замены вызывается с 5-ю аргументами: первый – всё совпадение, затем два аргумента содержимое скобок, затем (в примере не используются) индекс совпадения и исходная строка:
Если в регулярном выражении много скобочных групп, то бывает удобно использовать остаточные аргументы для обращения к ним:
Или, если мы используем именованные группы, то объект groups с ними всегда идёт последним, так что можно получить его так:
Использование функции даёт нам максимальные возможности по замене, потому что функция получает всю информацию о совпадении, имеет доступ к внешним переменным и может делать всё, что угодно.
regexp.exec(str)
Метод regexp.exec(str) ищет совпадение с regexp в строке str . В отличие от предыдущих методов, вызывается на регулярном выражении, а не на строке.
Он ведёт себя по-разному в зависимости от того, имеет ли регулярное выражение флаг g .
Если нет g , то regexp.exec(str) возвращает первое совпадение в точности как str.match(regexp) . Такое поведение не даёт нам ничего нового.
Но если есть g , то:
- Вызов regexp.exec(str) возвращает первое совпадение и запоминает позицию после него в свойстве regexp.lastIndex .
- Следующий такой вызов начинает поиск с позиции regexp.lastIndex , возвращает следующее совпадение и запоминает позицию после него в regexp.lastIndex .
- …И так далее.
- Если совпадений больше нет, то regexp.exec возвращает null , а для regexp.lastIndex устанавливается значение 0 .
Таким образом, повторные вызовы возвращают одно за другим все совпадения, используя свойство regexp.lastIndex для отслеживания текущей позиции поиска.
В прошлом, до появления метода str.matchAll в JavaScript, вызов regexp.exec в цикле использовали для получения всех совпадений с их позициями и группами скобок в цикле:
Это работает и сейчас, хотя для современных браузеров str.matchAll , как правило, удобнее.
Мы можем использовать regexp.exec для поиска совпадения, начиная с нужной позиции, если вручную поставим lastIndex .
Если у регулярного выражения стоит флаг y , то поиск будет вестись не начиная с позиции regexp.lastIndex , а только на этой позиции (не далее в тексте).
В примере выше заменим флаг g на y . Ничего найдено не будет, поскольку именно на позиции 5 слова нет:
Это удобно в тех ситуациях, когда мы хотим «прочитать» что-то из строки по регулярному выражению именно на конкретной позиции, а не где-то далее.
Если есть шаблон строки, состоящей из ограниченного квадратными скобками набора слов, разделенных точкой с запятой (где one, two, three — это любые слова)
то как проверить строку на соответствие этому шаблону, используя регулярные выражения?
1 ответ 1
- ^[ — открывающая квадратная скобка в начале строки;
- [ ]* — произвольное количество пробелов;
- [^ ;]+ — один или более символ, отличный от пробела и точки с запятой;
- (;[ ]*[^ ;]+)* — произвольное количество последовательностей из точки с запятой, нуля и более пробелов, одного и более символов;
- [ ]* — произвольное количество пробелов;
- ^[$ — закрывающая квадратная скобка в конце строки;
Введение в регулярные выражения
Регулярные выражения (RegExp) — это очень эффективный способ работы со строками.
Составив регулярное выражение с помощью специального синтаксиса вы можете:
- искать текст в строке
- заменять подстроки в строке
- извлекать информацию из строки
Почти во всех языках программирования есть регулярные выражения. Есть небольшие различия в реализации, но общие концепции применяются практически везде.
Регулярные выражения относятся к 1950-м годам, когда они были формализованы как концептуальный шаблон поиска для алгоритмов обработки строк.
Регулярные выражения реализованные в UNIX, таких как grep, sed и популярных текстовых редакторах, начали набирать популярность и были добавлены в язык программирования Perl, а позже и в множество других языков.
JavaScript, наряду с Perl, это один из языков программирования в котором поддержка регулярных выражений встроена непосредственно в язык.
Сложно, по полезно
Новичкам регулярные выражения могут показаться абсолютной ерундой, а зачастую даже и профессиональным разработчикам, если не вкладывать время необходимое для их понимания.
Регулярные выражения сложно писать, сложно читать и сложно поддерживать/изменять.
Но иногда регулярные выражения это единственный разумный способ выполнить какие-то манипуляции над строками, поэтому они являются очень ценным инструментом.
Это руководство нацелено на то чтобы самым простым способом дать вам некоторое представление о регулярных выражениях в JavaScript и предоставить информацию о том как читать и создавать регулярные выражения.
Эмпирическое правило заключается в том, что простые регулярные выражения просты для чтения и записи, в то время как сложные регулярные выражения могут быстро превратиться в беспорядок, если вы не глубоко понимаете основы.
Как выглядят регулярные выражения
В JavaScript регулярные выражения это объект, который может быть определён двумя способами.
Первый способ заключается в создании нового объекта RegExp с помощью конструктора:
Второй способ заключается в использовании литералов регулярных выражений:
Вы знаете что в JavaScript есть литералы объектов и литералы массивов? В нём также есть литералы regexp.
В приведённом выше примере hey называется шаблоном. В литеральной форме он находится между двумя слэшами, а в случае с конструктором объекта, нет.
Это первое важное отличие между двумя способами определения регулярных выражений, остальные мы увидим позже.
Как они работают?
Регулярное выражение, которое мы определили выше как re1 , очень простое. Оно ищет строку hey без каки-либо ограничений: строка может содержать много текста, а слово hey находиться где-то в середине и регулярное выражение сработает. Строка может содержать только слово hey и регулярка опять сработает.
Это довольно просто.
Вы можете попробовать протестировать регулярное выражение с помощью метода RegExp.test(String) , который возвращает логическое ( boolean ) значение:
В примере выше мы просто проверили удовлетворяет ли "hey" шаблону регулярного выражения, который храниться в re1 .
Это проще простого, но вы уже знаете много о регулярных выражениях.
Закрепление
сработает независимо от того где находится hey внутри строки.
Если вы хотите найти строки, которые начинаются с hey , то используйте оператор ^ :
Если вы хотите найти строки, которые заканчиваются на hey , то используйте оператор $ :
Объединяя два предыдущих оператора вы можете найти строку, которая полностью совпадает с hey :
Чтобы найти строку начинающуюся с одной подстроки, а заканчивающуюся другой подстрокой вы можете использовать .* , который будет совпадать с любым символом повторяющимся 0 или более раз:
Поиск элементов по диапазону
Вместо того чтобы искать определённую строку, вы можете указать диапазон символов, например:
Эти регулярные выражения ищут строки, которые содержат хотя бы один символ из выбранного диапазона:
Диапазоны можно комбинировать:
Поиск многократных совпадений элемента диапазона
Вы можете проверить содержит ли строка только один символ из диапазона с помощью символа — :
Инверсия шаблона
Символ ^ в начале шаблона привязывает его к началу строки.
Использование этого символа внутри диапазона инвертирует диапазон, поэтому:
Метасимволы
- d совпадает с любым числом, эквивалентно [0-9]
- D совпадает с любым символом, который не является числом, эквивалентно [^0-9]
- w совпадает с любым буквенно-числовым символом, эквивалентно [A-Za-z0-9]
- W совпадает с любым символом, который не является буквенно-числовым значением, эквивалентно [^A-Za-z0-9]
- s совпадает с любым пробельным символом: пробел, табуляция, символ новой строки и пробелы Unicode
- S совпадает с любым символом, который не является пробелом