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

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

Технический фундамент повторений

Квантификатор управляет числом повторений предыдущего токена:

  • токеном может быть символ, класс (\d, [A-Z]) или группа ((ab));
  • без группировки повторение часто применяется не к той части, которую ты ожидал;
  • жадность/ленивость влияет на границы совпадения;
  • в валидациях безопаснее явные диапазоны {n,m} + якоря.

Это помогает избежать "широких" совпадений и случайных пропусков.

Что решают квантификаторы

Часто важно не просто "какой символ", а "сколько раз он повторяется". Например: минимум 8 символов в пароле, ровно 4 цифры в PIN, необязательный префикс в коде. Квантификаторы в regex отвечают именно за количество повторений.

Ключевой момент: квантификатор применяется к символу, классу или группе, стоящей прямо перед ним.

Проверь себя: к чему относится + в шаблоне /ab+/ - к ab целиком или только к b?

Смотри, что важно: сравни область действия квантификатора с якорями (чтобы совпадение было "целиком").

console.log(/^ab+$/.test('abbb')); // true (b повторяется)
console.log(/^ab+$/.test('abab')); // false

console.log(/^(ab)+$/.test('abab')); // true (повторяется группа "ab")
console.log(/^(ab)+$/.test('abbb')); // false

Основные квантификаторы

  • * - 0 или больше;
  • + - 1 или больше;
  • ? - 0 или 1;
  • {n} - ровно n раз;
  • {n,} - минимум n раз;
  • {n,m} - от n до m раз.
console.log(/a*/.test('')); // true
console.log(/a+/.test('')); // false
console.log(/\d{4}/.test('PIN: 1234')); // true
console.log(/\d{4}/.test('PIN: 123')); // false

Смотри, что важно: * может дать совпадение даже с пустой строкой.

Примеры на практике

const passwordRegex = /^[A-Za-z0-9_]{8,20}$/;

console.log(passwordRegex.test('abc_1234')); // true
console.log(passwordRegex.test('short7')); // false

Здесь квантификатор {8,20} ограничивает длину строки.

Еще пример с необязательной частью:

const phoneRegex = /^\+?\d{10,12}$/;

console.log(phoneRegex.test('+380501112233')); // true
console.log(phoneRegex.test('380501112233')); // true

? после \+ делает плюс необязательным.

Жадные и ленивые квантификаторы

По умолчанию квантификаторы жадные (greedy) - берут максимально возможное совпадение.

const text = '<b>one</b><b>two</b>';
console.log(text.match(/<b>.*<\/b>/)); // захватит слишком много

Ленивый режим (lazy) добавляется через ? после квантификатора.

console.log(text.match(/<b>.*?<\/b>/)); // первый блок <b>one</b>

Здесь часто путаются: ? может быть и "0 или 1", и "сделай квантификатор ленивым" - зависит от позиции.

Проверь себя: почему .* в HTML-подобном тексте часто дает неожиданный результат?

Микро-сценарии

  1. Проверка длины кода подтверждения (^\d{6}$).
  2. Валидация идентификатора заказа (^[A-Z]{3}-\d{5}$).
  3. Очистка пользовательского ввода с повторяющимися пробелами (\s+).
const normalized = 'Hi    there'.replace(/\s+/g, ' ');
console.log(normalized); // Hi there

Дополнительный пример: повторение группы, а не отдельного символа.

console.log(/^(ab){3}$/.test('ababab')); // true
console.log(/^(ab){3}$/.test('aba')); // false

Частые ошибки новичков

  • Ставить квантификатор не к той части шаблона.
  • Забывать, что * пропускает пустые строки.
  • Использовать жадный .* там, где нужен более точный шаблон.
  • Не ограничивать длину и получать "слишком широкие" совпадения.

Анти-провал: при любой валидации длины старайся использовать явные {n,m} и якоря начала/конца (^, $).

Что будет, если изменить входные данные

Для ^\d{6}$:

  • 123456 пройдет;
  • 12345 не пройдет (мало цифр);
  • 1234567 не пройдет (слишком много);
  • 123a56 не пройдет (не цифра).

Проверь себя: почему без ^ и $ строка id=123456-ok может считаться совпадением?

Краткий итог

  • Квантификаторы управляют количеством повторений символов и групп.
  • *, +, ?, {n,m} закрывают большинство практических сценариев.
  • По умолчанию квантификаторы жадные; для точности иногда нужен ленивый режим.
  • Явные ограничения длины повышают надежность валидации.
  • Большинство ошибок связано с неправильной областью действия квантификатора и отсутствием якорей.