RegExp.exec() возвращает NULL спорадически
Я серьезно схожу с ума по этому поводу, и я уже потратил непропорциональное количество времени на попытку выяснить, что происходит здесь. Поэтому, пожалуйста, дайте мне руку =)
Мне нужно выполнить некоторое соответствие RegExp строк в JavaScript. К сожалению, это ведет себя очень странно. Этот код:
var rx = /(cat|dog)/gi;
var w = new Array("I have a cat and a dog too.", "There once was a dog and a cat.", "I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.");
for (var i in w) {
var m = null;
m = rx.exec(w[i]);
if(m){
document.writeln("<pre>" + i + "\nINPUT: " + w[i] + "\nMATCHES: " + m.slice(1) + "</pre>");
}else{
document.writeln("<pre>" + i + "\n'" + w[i] + "' FAILED.</pre>");
}
}
Возвращает "cat" и "dog" для первых двух элементов, как и должно быть, но затем некоторые exec()
-calls начинают возвращать null
. Я не понимаю, почему.
Я разместил здесь Fiddle где вы можете запускать и редактировать код.
И пока я пробовал это в Chrome и Firefox.
Ура!
/Christofer
Ответы
Ответ 1
О, вот оно. Поскольку вы определяете глобальное выражение regex, оно соответствует первому cat
и второму проходу цикла dog
. Итак, в основном вам просто нужно reset ваше регулярное выражение (его внутренний указатель). Ср это:
var w = new Array("I have a cat and a dog too.", "I have a cat and a dog too.", "I have a cat and a dog too.", "I have a cat and a dog too.");
for (var i in w) {
var rx = /(cat|dog)/gi;
var m = null;
m = rx.exec(w[i]);
if(m){
document.writeln("<p>" + i + "<br/>INPUT: " + w[i] + "<br/>MATCHES: " + w[i].length + "</p>");
}else{
document.writeln("<p><b>" + i + "<br/>'" + w[i] + "' FAILED.</b><br/>" + w[i].length + "</p>");
}
document.writeln(m);
}
Ответ 2
Объект regex имеет свойство lastIndex
, которое обновляется при запуске exec
. Поэтому, когда вы выполняете регулярное выражение, например, "У меня есть кошка и собака тоже". lastIndex
устанавливается в 12. При следующем запуске exec
в том же объекте регулярного выражения он начинает искать индекс 12. Таким образом, вы должны reset lastIndex
между каждым прогоном.
Ответ 3
Две вещи:
- Указанная потребность reset при использовании флага
g
(global). Чтобы решить эту проблему, я рекомендовал просто назначить 0
члену lastIndex
объекта RegExp
. Это улучшает производительность, чем уничтожает и восстанавливает.
- Будьте осторожны, когда используйте ключевое слово
in
, чтобы пройти объект Array
, потому что это может привести к неожиданным результатам с некоторыми lib. Иногда вам нужно проверить с чем-то вроде isNaN(i)
, или если вы знаете, что у него нет отверстий, используйте классический для цикла.
Код может быть:
var rx = /(cat|dog)/gi;
w = ["I have a cat and a dog too.", "There once was a dog and a cat.", "I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat.","I have a cat and a dog too.", "There once was a dog and a cat."];
for (var i in w)
if(!isNaN(i)) // Optional, check it is an element if Array could have some odd members.
{
var m = null;
m = rx.exec(w[i]); // Run
rx.lastIndex = 0; // Reset
if(m)
{
document.writeln("<pre>" + i + "\nINPUT: " + w[i] + "\nMATCHES: " + m.slice(1) + "</pre>");
} else {
document.writeln("<pre>" + i + "\n'" + w[i] + "' FAILED.</pre>");
}
}
Ответ 4
У меня была аналогичная проблема с использованием только /g, и предлагаемое решение здесь не работало для меня в FireFox 3.6.8. Я получил script с
var myRegex = new RegExp("my string", "g");
Я добавляю это, если у кого-то другая проблема, с которой я столкнулся с вышеупомянутым решением.