- Методы RegExp и String
- str.match(regexp)
- str.matchAll(regexp)
- str.split(regexp|substr, limit)
- str.search(regexp)
- str.replace(str|regexp, str|func)
- regexp.exec(str)
- regexp.test(str)
- String.prototype.search()
- Try it
- Syntax
- Parameters
- Return value
- Description
- Examples
- Using search()
- Specifications
- Browser compatibility
- See also
- Found a content problem with this page?
Методы RegExp и String
В этой главе мы рассмотрим все детали методов для работы с регулярными выражениями.
str.match(regexp)
Метод str.match(regexp) ищет совпадения с regexp в строке str .
У него есть три режима работы:
- Если у регулярного выражения нет флага g , то он возвращает первое совпадение в виде массива со скобочными группами и свойствами index (позиция совпадения), input (строка поиска, равна str ):
let str = "I love JavaScript"; let result = str.match(/Java(Script)/); alert( result[0] ); // JavaScript (всё совпадение) alert( result[1] ); // Script (первые скобки) alert( result.length ); // 2 // Дополнительная информация: alert( result.index ); // 7 (позиция совпадения) alert( result.input ); // I love JavaScript (исходная строка)
let str = "I love JavaScript"; let result = str.match(/Java(Script)/g); alert( result[0] ); // JavaScript alert( result.length ); // 1
let str = "I love JavaScript"; let result = str.match(/HTML/); alert(result); // null alert(result.length); // Ошибка: у null нет свойства length
let result = str.match(regexp) || [];
str.matchAll(regexp)
Метод str.matchAll(regexp) – «новый, улучшенный» вариант метода str.match .
Он используется, в первую очередь, для поиска всех совпадений вместе со скобочными группами.
У него 3 отличия от match :
- Он возвращает не массив, а перебираемый объект с результатами, обычный массив можно сделать при помощи Array.from .
- Каждое совпадение возвращается в виде массива со скобочными группами (как str.match без флага g ).
- Если совпадений нет, то возвращается не null , а пустой перебираемый объект.
let str = 'Hello, world!
'; let regexp = /<(.*?)>/g; let matchAll = str.matchAll(regexp); alert(matchAll); // [object RegExp String Iterator], не массив, а перебираемый объект matchAll = Array.from(matchAll); // теперь массив let firstMatch = matchAll[0]; alert( firstMatch[0] ); // alert( firstMatch[1] ); // h1 alert( firstMatch.index ); // 0 alert( firstMatch.input ); // Hello, world!
При переборе результатов matchAll в цикле for..of вызов Array.from , разумеется, не нужен.
str.split(regexp|substr, limit)
Разбивает строку в массив по разделителю – регулярному выражению regexp или подстроке substr.
Обычно мы используем метод split со строками, вот так:
alert('12-34-56'.split('-')) // массив [12, 34, 56]
Но мы можем разделить по регулярному выражению аналогичным образом:
alert('12, 34, 56'.split(/,\s*/)) // массив [12, 34, 56]
str.search(regexp)
Метод str.search(regexp) возвращает позицию первого совпадения с regexp в строке str или -1 , если совпадения нет.
let str = "Я люблю JavaScript!"; let regexp = /Java.+/; alert( str.search(regexp) ); // 8
Важное ограничение: str.search умеет возвращать только позицию первого совпадения.
Если нужны позиции других совпадений, то следует использовать другой метод, например, найти их все при помощи str.matchAll(regexp) .
str.replace(str|regexp, str|func)
Это универсальный метод поиска-и-замены, один из самых полезных. Этакий швейцарский армейский нож для поиска и замены в строке.
Мы можем использовать его и без регулярных выражений, для поиска-и-замены подстроки:
// заменить тире двоеточием alert('12-34-56'.replace("-", ":")) // 12:34-56
Хотя есть подводный камень.
Когда первый аргумент replace является строкой, он заменяет только первое совпадение.
Вы можете видеть это в приведённом выше примере: только первый «-» заменяется на «:» .
Чтобы найти все дефисы, нам нужно использовать не строку «-» , а регулярное выражение /-/g с обязательным флагом g :
// заменить все тире двоеточием alert( '12-34-56'.replace( /-/g, ":" )) // 12:34:56
Второй аргумент – строка замены. Мы можем использовать специальные символы в нем:
Спецсимволы | Действие в строке замены |
---|---|
$& | вставляет всё найденное совпадение |
$` | вставляет часть строки до совпадения |
$’ | вставляет часть строки после совпадения |
$n | если n это 1-2 значное число, то вставляет содержимое n-й скобки (см. главу Скобочные группы) |
$ | вставляет содержимое скобки с указанным name (см. главу Скобочные группы) |
$$ | вставляет «$» |
let str = "John Smith"; // поменять местами имя и фамилию alert(str.replace(/(\w+) (\w+)/i, '$2, $1')) // Smith, John
Для ситуаций, которые требуют «умных» замен, вторым аргументом может быть функция.
Она будет вызываться для каждого совпадения, и её результат будет вставлен в качестве замены.
Функция вызывается с аргументами func(match, p1, p2, . pn, offset, input, groups) :
- match – найденное совпадение,
- p1, p2, . pn – содержимое скобок (см. главу Скобочные группы).
- offset – позиция, на которой найдено совпадение,
- input – исходная строка,
- groups – объект с содержимым именованных скобок (см. главу Скобочные группы).
Если скобок в регулярном выражении нет, то будет только 3 аргумента: func(match, offset, input) .
Например, переведём выбранные совпадения в верхний регистр:
let str = "html and css"; let result = str.replace(/html|css/gi, str => str.toUpperCase()); alert(result); // HTML and CSS
Заменим каждое совпадение на его позицию в строке:
alert("Хо-Хо-хо".replace(/хо/gi, (match, offset) => offset)); // 0-3-6
В примере ниже две скобки, поэтому функция замены вызывается с 5-ю аргументами: первый – всё совпадение, затем два аргумента содержимое скобок, затем (в примере не используются) индекс совпадения и исходная строка:
let str = "John Smith"; let result = str.replace(/(\w+) (\w+)/, (match, name, surname) => `$, $`); alert(result); // Smith, John
Если в регулярном выражении много скобочных групп, то бывает удобно использовать остаточные аргументы для обращения к ним:
let str = "John Smith"; let result = str.replace(/(\w+) (\w+)/, (. match) => `$, $`); alert(result); // Smith, John
Или, если мы используем именованные группы, то объект groups с ними всегда идёт последним, так что можно получить его так:
let str = "John Smith"; let result = str.replace(/(?\w+) (?\w+)/, (. match) => < let groups = match.pop(); return `$, $`; >); alert(result); // Smith, John
Использование функции даёт нам максимальные возможности по замене, потому что функция получает всю информацию о совпадении, имеет доступ к внешним переменным и может делать всё что угодно.
regexp.exec(str)
Метод regexp.exec(str) ищет совпадение с regexp в строке str . В отличие от предыдущих методов, вызывается на регулярном выражении, а не на строке.
Он ведёт себя по-разному в зависимости от того, имеет ли регулярное выражение флаг g .
Если нет g , то regexp.exec(str) возвращает первое совпадение в точности как str.match(regexp) . Такое поведение не даёт нам ничего нового.
- Вызов regexp.exec(str) возвращает первое совпадение и запоминает позицию после него в свойстве regexp.lastIndex .
- Следующий такой вызов начинает поиск с позиции regexp.lastIndex , возвращает следующее совпадение и запоминает позицию после него в regexp.lastIndex .
- …И так далее.
- Если совпадений больше нет, то regexp.exec возвращает null , а для regexp.lastIndex устанавливается значение 0 .
Таким образом, повторные вызовы возвращают одно за другим все совпадения, используя свойство regexp.lastIndex для отслеживания текущей позиции поиска.
В прошлом, до появления метода str.matchAll в JavaScript, вызов regexp.exec использовали для получения всех совпадений с их позициями и группами скобок в цикле:
let str = 'Больше о JavaScript на https://javascript.info'; let regexp = /javascript/ig; let result; while (result = regexp.exec(str)) < alert( `Найдено $на позиции $` ); // Найдено JavaScript на позиции 9, затем // Найдено javascript на позиции 31 >
Это работает и сейчас, хотя для современных браузеров str.matchAll , как правило, удобнее.
Мы можем использовать regexp.exec для поиска совпадения, начиная с нужной позиции, если вручную поставим lastIndex .
let str = 'Hello, world!'; let regexp = /\w+/g; // без флага g свойство lastIndex игнорируется regexp.lastIndex = 5; // ищем с 5-й позиции (т.е с запятой и далее) alert( regexp.exec(str) ); // world
Если у регулярного выражения стоит флаг y , то поиск будет вестись не начиная с позиции regexp.lastIndex , а только на этой позиции (не далее в тексте).
В примере выше заменим флаг g на y . Ничего найдено не будет, поскольку именно на позиции 5 слова нет:
let str = 'Hello, world!'; let regexp = /\w+/y; regexp.lastIndex = 5; // ищем ровно на 5-й позиции alert( regexp.exec(str) ); // null
Это удобно в тех ситуациях, когда мы хотим «прочитать» что-то из строки по регулярному выражению именно на конкретной позиции, а не где-то далее.
regexp.test(str)
Метод regexp.test(str) ищет совпадение и возвращает true/false , в зависимости от того, находит ли он его.
let str = "Я люблю JavaScript"; // эти два теста делают одно и то же alert( /люблю/i.test(str) ); // true alert( str.search(/люблю/i) != -1 ); // true
Пример с отрицательным ответом:
let str = "Ля-ля-ля"; alert( /люблю/i.test(str) ); // false alert( str.search(/люблю/i) != -1 ); // false
Если регулярное выражение имеет флаг g , то regexp.test ищет, начиная с regexp.lastIndex и обновляет это свойство, аналогично regexp.exec .
Таким образом, мы можем использовать его для поиска с заданной позиции:
let regexp = /люблю/gi; let str = "Я люблю JavaScript"; // начать поиск с 10-й позиции: regexp.lastIndex = 10; alert( regexp.test(str) ); // false (совпадений нет)
Одно и то же регулярное выражение, использованное повторно на другом тексте, может дать другой результат
Если мы применяем одно и то же регулярное выражение последовательно к разным строкам, это может привести к неверному результату, поскольку вызов regexp.test обновляет свойство regexp.lastIndex , поэтому поиск в новой строке может начаться с ненулевой позиции.
Например, здесь мы дважды вызываем regexp.test для одного и того же текста, и второй раз поиск завершается уже неудачно:
let regexp = /javascript/g; // (regexp только что создан: regexp.lastIndex=0) alert( regexp.test("javascript") ); // true (теперь regexp.lastIndex=10) alert( regexp.test("javascript") ); // false
Это именно потому, что во втором тесте regexp.lastIndex не равен нулю.
Чтобы обойти это, можно присвоить regexp.lastIndex = 0 перед новым поиском. Или вместо методов на регулярном выражении вызывать методы строк str.match/search/. , они не используют lastIndex .
String.prototype.search()
The search() method executes a search for a match between a regular expression and this String object.
Try it
Syntax
Parameters
A regular expression object, or any object that has a Symbol.search method.
If regexp is not a RegExp object and does not have a Symbol.search method, it is implicitly converted to a RegExp by using new RegExp(regexp) .
Return value
The index of the first match between the regular expression and the given string, or -1 if no match was found.
Description
The implementation of String.prototype.search() itself is very simple — it simply calls the Symbol.search method of the argument with the string as the first parameter. The actual implementation comes from RegExp.prototype[@@search]() .
The g flag of regexp has no effect on the search() result, and the search always happens as if the regex’s lastIndex is 0. For more information on the behavior of search() , see RegExp.prototype[@@search]() .
When you want to know whether a pattern is found, and also know its index within a string, use search() .
- If you only want to know if it exists, use the RegExp.prototype.test() method, which returns a boolean.
- If you need the content of the matched text, use match() or RegExp.prototype.exec() .
Examples
Using search()
The following example searches a string with two different regex objects to show a successful search (positive value) vs. an unsuccessful search ( -1 ).
const str = "hey JudE"; const re = /[A-Z]/; const reDot = /[.]/; console.log(str.search(re)); // returns 4, which is the index of the first capital letter "J" console.log(str.search(reDot)); // returns -1 cannot find '.' dot punctuation
Specifications
Browser compatibility
BCD tables only load in the browser
See also
Found a content problem with this page?
This page was last modified on Apr 5, 2023 by MDN contributors.
Your blueprint for a better internet.