Я серьезно схожу с ума по этому поводу, и я уже потратил непропорционально много времени, пытаясь понять, что здесь происходит. Так что дайте мне руку, пожалуйста =)
Мне нужно выполнить сопоставление строк в JavaScript с помощью RegExp. К сожалению, ведет себя очень странно. Этот код:
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>");
}
}
Возвращает «кошка» и «собака» для первых двух элементов, как и должно быть, но затем некоторые exec()
-calls начинают возвращаться null
. Не понимаю почему.
Я отправил скрипку здесь , где вы можете запускать и редактировать код.
И до сих пор я пробовал это в Chrome и Firefox.
Ура!
/ Кристофер
javascript
regex
cpak
источник
источник
"I have a cat and a dog too."
, кажется,Ответы:
О, вот оно. Поскольку вы определяете свое глобальное регулярное выражение, оно совпадает сначала
cat
и на втором проходе циклаdog
. Итак, в основном вам просто нужно сбросить ваше регулярное выражение (это внутренний указатель). Ср. это: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); }
источник
У объекта регулярного выражения есть свойство,
lastIndex
которое обновляется при запускеexec
. Поэтому, когда вы выполняете регулярное выражение, например, «У меня есть кошка и собака тоже.»,lastIndex
Устанавливается значение 12. В следующий раз, когда вы запускаетеexec
тот же объект регулярного выражения, он начинает поиск с индекса 12. Поэтому вам нужно сброситьlastIndex
свойство между каждым запуском.источник
myRe.lastIndex = 0;
для последующего использования.Две вещи:
g
(глобального) флага. Чтобы решить эту проблему , я recommed просто правопреемником0
кlastIndex
членуRegExp
объекта. У этого есть лучшая производительность, чем у уничтожения и воссоздания.in
ключевого слова для обходаArray
объекта, поскольку это может привести к неожиданным результатам с некоторыми библиотеками. Иногда вам следует проверить что-нибудь вродеisNaN(i)
, или, если вы знаете, что в нем нет дыр, используйте классический цикл for.Код может быть:
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>"); } }
источник
rx.lastIndex = 0
намного лучше, чем воссоздание объекта RegEx внутри цикла.У меня была аналогичная проблема с использованием только / g, и предлагаемое здесь решение не сработало для меня в FireFox 3.6.8. Мой сценарий работает с
var myRegex = new RegExp("my string", "g");
Я добавляю это на тот случай, если у кого-то еще возникнет такая же проблема, как и с указанным выше решением.
источник