Символьные классы и квантификаторы

Символьные классы и квантификаторы #

Символьный класс в regex задаёт множество допустимых символов в одной позиции; квантификатор указывает, сколько раз элемент может повторяться. Вместе они описывают форматы SKU, телефонов, почтовых индексов и полей чекаута без перечисления каждого варианта вручную.


Один символ: . и экранирование #

Точка . совпадает с любым символом, кроме перевода строки (без флага s):

'KB-01'.match(/K./) // ['K-']

Спецсимволы regex экранируют обратным слэшем: \. \* \+ \? \^ \$ \| \( \) \[ \] \{ \}

'цена: 1500'.match(/цена: \d+/) // ['цена: 1500']

Предопределённые классы #

КлассЗначениеПротивоположность
\dцифра [0-9]\D — не цифра
\wбуква, цифра, _\W — не \w
\sпробельный символ\S — не пробел
const phone = '+7 (999) 111-22-33'
phone.replace(/\D/g, '') // "79991112233"

const sku = 'KB-01-XL'
/^\w{2}-\d{2}-\w{2}$/.test(sku) // true — упрощённая схема

\w в JavaScript соответствует [A-Za-z0-9_] и не включает кириллицу. Для русских букв используйте явный класс [а-яёА-ЯЁ] с флагом u при необходимости.


Набор в квадратных скобках [...] #

Внутри [] перечисляют допустимые символы:

/^[A-Z]{2}$/.test('RU') // true — две заглавные латинские
/^[0-9]{6}$/.test('119021') // true — шесть цифр индекса

Диапазон через дефис:

/[a-z0-9-]/.test('focus-tracks') // true

Отрицание — [^...] — «любой символ, кроме перечисленных»:

'доставка: 45 мин'.match(/[^0-9]+/g)
// ['доставка: ', ' мин']

Внутри класса большинство спецсимволов теряют смысл; экранируйте ], \, ^ (если первый), - (если между символами диапазона).


Якоря и границы слова #

СимволЗначение
^начало строки (или строки в режиме m)
$конец строки
\bграница слова
\Bне граница слова
/^express$/i.test('express') // true — вся строка
/express/.test('delivery-express') // true — подстрока

/\bRUB\b/.test('цена 1500 RUB') // true
/\bRUB\b/.test('RUBBER') // false — RUB внутри слова

Для SKU и ID заказа якоря ^ $ обязательны при валидации «целиком»:

const SKU = /^[A-Z]{2}-\d{2}-[A-Z0-9]{1,3}$/
SKU.test('KB-01-XL') // true
SKU.test('prefix-KB-01-XL') // false

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

КвантификаторЗначение
*0 или более
+1 или более
?0 или 1
{n}ровно n
{n,}n или более
{n,m}от n до m
'ord-2026-7f3a'.match(/ord-\d{4}-[a-f0-9]{4}/)
// ['ord-2026-7f3a']

'ул. Пример, д. 5'.match(/\d+/) // ['5']
'д. 5, кв. 12'.match(/\d+/g) // ['5', '12']

Жадность по умолчанию: + и * захватывают максимум символов. Ленивый вариант — после квантификатора ?:

const html = '<span>товар</span><span>доставка</span>'
html.match(/<span>.*<\/span>/) // жадно — одно длинное совпадение
html.match(/<span>.*?<\/span>/g) // лениво — два коротких

Группировка без захвата #

Обычные скобки (...) создают захватывающую группу (см. Группы). Для только повторения фрагмента — незахватывающая группа (?:...):

const timeSlots = '10:00, 14:30, 18:00'
timeSlots.match(/(?:\d{2}:){2}\d{2}/g)
// ['10:00', '14:30', '18:00']

Практика: валидация полей доставки #

const POSTAL_CODE = /^\d{6}$/
const PHONE_RU = /^\+7\d{10}$/

function validateDeliveryForm({ zip, phone }) {
  const errors = {}
  if (!POSTAL_CODE.test(zip)) errors.zip = 'Индекс: 6 цифр'
  const normalized = phone.replace(/\D/g, '')
  if (!PHONE_RU.test(`+${normalized}`)) errors.phone = 'Формат +7XXXXXXXXXX'
  return errors
}

validateDeliveryForm({ zip: '119021', phone: '+7 999 111 22 33' })
// {}
const PROMO = /^SAVE-\d{2}$/i

function applyPromo(code) {
  return PROMO.test(code.trim()) ? code.toUpperCase() : null
}

applyPromo('save-15') // "SAVE-15"
applyPromo('DISCOUNT') // null
function parseCartQuantities(line) {
  // "клавиатура x2, мышь x1"
  const re = /(\p{L}+)\s+x(\d+)/gu
  const items = []
  for (const [, name, qty] of line.matchAll(re)) {
    items.push({ name, qty: Number(qty) })
  }
  return items
}

parseCartQuantities('клавиатура x2, мышь x1')
// [{ name: 'клавиатура', qty: 2 }, { name: 'мышь', qty: 1 }]

Итог #

  • Предопределённые классы \d, \w, \s и их отрицания покрывают типичные наборы символов.
  • Набор [...] и [^...] задаёт точный или запрещающий алфавит на позиции.
  • Квантификаторы *, +, ?, {n,m} управляют повторением; ? после них делает поиск ленивым.
  • Якоря ^ $ и \b разделяют «вся строка» и «граница слова» — критично для валидации форм.

См. также #