Странное поведение regex с глобальным флагом
У меня есть регулярное выражение для поиска специальных символов:
pattern = /\W|_/g
Оно работает нормально для большинства символов, но с символом * ведет себя странно.
Вот мои тесты:
pattern = /\W|_/g
pattern.test('abc_')
// true
pattern.test('abc*')
// false
pattern.test("SELECT * FROM table")
// true
pattern.test("SELECT * FROM table")
// true
pattern.test('abc*')
// false
Когда я убираю глобальный флаг g, все работает как надо:
pattern = /\W|_/
pattern.test('abc*')
// true
pattern.test('abc')
// false
pattern.test('SELECT * FROM table')
// true
Почему так происходит? В чем разница между использованием regex с флагом g и без него при вызове метода test()?
Да, это классическая ловушка с глобальным флагом. Регулярка с g сохраняет позицию через lastIndex. Первый test() находит совпадение - lastIndex становится позицией после найденного символа. Следующий test() начинает поиск оттуда, а не с начала. Хочешь использовать g? Обнуляй pattern.lastIndex = 0 перед каждым поиском. Или просто не используй g для test() - он нужен для match() и replace().
Да, точно! lastIndex показывает, где закончился последний поиск, и следующий test() стартует оттуда. Хочешь искать с начала — сбрось lastIndex перед test(). Без флага g всегда ищет сначала.
флаг g делает регулярку “запоминающей” где она остановилась. каждый regex объект хранит внутри lastIndex - он сбрасывается на 0 только после неудачного поиска или когда строка закончилась. поэтому когда вызываешь test() несколько раз подряд с флагом g, поиск идёт не с начала строки, а оттуда где закончился предыдущий. второй вызов pattern.test(‘abc*’) возвращает false именно поэтому - регулярка ищет с позиции после найденного ‘*’. чтобы исправить: либо убери флаг g для test(), либо создавай новый объект регулярки каждый раз.