Pull to refresh

Регулярная ловушка

Reading time 2 min
Views 3.3K
Допустим, мы хотим проверить регулярным выражением, что в строке есть хотя бы одна цифра. Пишем код:

<script>

var digits = /([0-9])+/g;

function has_digit(s) { return digits.test(s); }

</script>


Этот код неверен.
Вам очевидно — почему? Если нет — добро пожаловать под кат!



Кстати, убедитесь сами:

<script>

document.write(has_digit("abc0xyz") + ' ' + has_digit("abc0xyz"));

</script>


Получаем:

true false

А должны, конечно:

true true

Функция has_digit() регулярно дает неверный ответ. Обратимся к всемирному разуму Сети.

http://javascript.ru

Чтобы просто узнать, подходит ли строка под регулярное выражение regexp, используйте regexp.test(string).

Двойка, ответ неверный.

http://www.regular-expressions.info

The test() function of the RegExp object is a shortcut to exec() != null. It takes the subject string as a paarameter and returns true or false depending on whether the regex matches part of the string or not.

Двойка, ответ неверный.

И т.д.

Long story short. Читаем стандарт.

RegExp.prototype.test(string)
Equivalent to the expression RegExp.prototype.exec(string)!=null.


Значит дело в волшебных пузырьках функции RegExp.prototype.exec(string).

Ее алгоритм таков: при наличии флага g у регулярного выражения поиск совпадений начинается со свойства lastIndex (это свойство регулярного выражения). Вначале оно равно нулю, но после удачного поиска обновляется позицией для поиска очередного совпадения.

Вот и решение. У глобальных регулярных выражений функция test() не обязательно ищет совпадения с начала строки.

Проблема усугубляется тем, что обычно регулярное выражение применяют в форме:

/([0-9])+/g.test("abc")


Этот код не вызывает проблем. Почему? Нетрудно видеть, что каждый раз при выполнении этого кода создается новое регулярное выражение и поиск идет с нулевой позиции.

Разумеется, не я первый наступил на эти грабли.

http://stackoverflow.com

Удивляет, что большинство сетевых ресурсов по JavaScript оказались бесполезны.

Надеюсь, кому-то эта информация сбережет драгоценное время…

UDP

Да, global flag в данном случае не нужен.

Еще раз — если Вы поняли, что не так — под кат можно было и не ходить :-)

Tags:
Hubs:
+115
Comments 54
Comments Comments 54

Articles