Методы RegExp и String

Методы RegExp и String #

Методы RegExp (test, exec) и методы String с аргументом regex (match, matchAll, replace, split) — основной API поиска и преобразования текста. Выбор метода зависит от того, нужна ли только проверка, первое совпадение, все совпадения или замена с группами.


RegExp.prototype.test(str) #

Возвращает boolean — есть ли совпадение. С флагом g или y обновляет lastIndex:

const ORDER = /^ord-\d{4}-[a-f0-9]{4}$/

ORDER.test('ord-2026-7f3a') // true
ORDER.test('invalid') // false

Для глобального regex повторные вызовы продолжают с lastIndex:

const tagRe = /\[(\w+)\]/g
const note = '[urgent] доставка [express]'

tagRe.test(note) // true — [urgent]
tagRe.test(note) // true — [express]
tagRe.test(note) // false
tagRe.lastIndex = 0 // сброс перед новым циклом

Для разовой проверки формата создавайте regex без g или сбрасывайте lastIndex.


RegExp.prototype.exec(str) #

Возвращает массив с совпадением или null. Элемент [0] — полное совпадение, [1], [2] — группы; свойство index — позиция, input — исходная строка:

const re = /(\d+)\s*(RUB|USD)/
const m = re.exec('доставка 300 RUB')

m[0] // "300 RUB"
m[1] // "300"
m[2] // "RUB"
m.index // 9

С флагом g каждый exec возвращает следующее совпадение — классический цикл:

const amountRe = /(\d+)\s*₽/g
const text = 'товар 1500 ₽, доставка 300 ₽'
let match

while ((match = amountRe.exec(text)) !== null) {
  console.log(Number(match[1]))
}
// 1500, 300

Для итерации по всем совпадениям предпочтительнее matchAll (см. ниже).


String.prototype.match(regexp) #

Без флага g — как один вызов exec: массив с группами или null:

'status: shipped'.match(/status:\s*(\w+)/)
// ['status: shipped', 'shipped', index: 0, input: '...', groups: undefined]

С флагом g — массив всех полных совпадений без групп:

'RUB USD RUB'.match(/\w{3}/g) // ['RUB', 'USD', 'RUB']

Если нужны группы для каждого вхождения — matchAll, не match с g.


String.prototype.matchAll(regexp) #

Итератор совпадений; обязателен флаг g (или y):

const re = /(?<sku>[A-Z]{2}-\d{2}) x(?<qty>\d+)/g
const cartLine = 'KB-01 x2, MS-03 x1'

for (const m of cartLine.matchAll(re)) {
  console.log(m.groups.sku, m.groups.qty)
}
// KB-01 2
// MS-03 1

Преобразование в массив:

const tracks = [...'a1|b2|c3'.matchAll(/(?<id>\w)(?<n>\d)/g)]
tracks.map((m) => m.groups) // [{ id: 'a', n: '1' }, ...]

String.prototype.replace(regexp, replacement) #

Без g — только первое совпадение. Замена строкой с $1, $<name>:

'ord-2026-7f3a'.replace(/(ord)-(\d{4})-([a-f0-9]{4})/, '$1:$2:$3')
// "ord:2026:7f3a"

С флагом g — все вхождения:

'1500 руб, 300 руб'.replace(/руб/gi, '₽')
// "1500 ₽, 300 ₽"

Функция-заменитель получает совпадение, группы, позицию, исходную строку:

function maskPan(value) {
  return value.replace(/\d(?=\d{4})/g, '*')
}

maskPan('4111 1111 1111 4242') // "**** **** **** 4242"

Спецпоследовательности в строке замены: $$$, $& — полное совпадение, $` — текст перед совпадением, $' — после.


String.prototype.split(regexp) #

Разбивает строку по разделителю-шаблону:

'focus, work , chill'.split(/\s*,\s*/)
// ["focus", "work", "chill"]

С захватывающими группами в разделителе фрагменты групп попадают в массив:

'artist—title|artist2—title2'.split(/\|/)
// ["artist—title", "artist2—title2"]

'key=value&foo=bar'.split(/[&=]/)
// ["key", "value", "foo", "bar"] — группы не использованы

Для CSV с кавычками простой split недостаточен — нужен парсер или более сложный regex.


Сводка: какой метод выбрать #

ЗадачаМетод
Валиден ли форматre.test(str)
Первое совпадение с группамиre.exec(str) или str.match(re)
Все совпадения без группstr.match(/.../g)
Все совпадения с группамиstr.matchAll(/.../g)
Заменаstr.replace(re, ...)
Разделить по шаблонуstr.split(re)

Практика: нормализация чекаута #

function parseCheckoutTotals(raw) {
  const lines = raw.trim().split(/\n+/)
  const itemRe = /^(?<name>.+?)\s+—\s+(?<sum>\d+)\s*₽$/
  const items = []

  for (const line of lines) {
    const m = line.match(itemRe)
    if (m) items.push({ name: m.groups.name.trim(), sum: Number(m.groups.sum) })
  }
  return items
}

parseCheckoutTotals(`Клавиатура — 4500 ₽
Доставка express — 300 ₽`)
// [{ name: 'Клавиатура', sum: 4500 }, { name: 'Доставка express', sum: 300 }]
function redactTrackingCodes(text) {
  return text.replace(/\bTRK-[A-Z0-9]{4,}\b/g, '[TRACKING]')
}

redactTrackingCodes('Трек TRK-9X2A прибыл')
// "Трек [TRACKING] прибыл"
const SLUG_INVALID = /[^a-z0-9-]+/g

function toPlaylistSlug(title) {
  return title
    .trim()
    .toLowerCase()
    .replace(SLUG_INVALID, '-')
    .replace(/-+/g, '-')
    .replace(/^-|-$/g, '')
}

toPlaylistSlug('  Summer Hits 2026!!  ')
// "summer-hits-2026"

Итог #

  • test — быстрая проверка; с g/y следите за lastIndex.
  • exec и match без g возвращают одно совпадение с группами; match с g — только строки совпадений.
  • matchAll — стандартный способ обхода всех вхождений с именованными группами.
  • replace с функцией гибче строковой замены; split принимает regex как разделитель.

См. также #