2011-01-18 5 views
52

Я серьезно схожу с ума по этому поводу, и я уже потратил непропорциональное количество времени на попытку выяснить, что здесь происходит. Поэтому, пожалуйста, дайте мне руку =)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>"); 
    } 
} 

Возвращает «кошка» и «собака» в течение первых двух элементов, как это должно быть, но тогда некоторые exec() -calls начать возвращение null. Я не понимаю, почему.

Я отправил Fiddle here, где вы можете запускать и редактировать код.

И пока я пробовал это в Chrome и Firefox.

Приветствия!

/Christofer

+0

он не только на '«У меня есть кошка и собака тоже.»', Кажется, – SilentGhost

+0

Exec возвращает нулевое значение, если совпадение не по дизайну, так по какой-то причине он не подходит. –

ответ

47

О, вот оно. Поскольку вы определяете глобальное регулярное выражение, оно совпадает с первым 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); 
} 
+0

там у нас есть, я был слишком медленным :) –

+0

ах сладкий! мне потребовалось бы некоторое время, чтобы понять это.благодаря! – cpak

+0

О, мужик, спасибо за это! – Stephen

48

Объект регулярного выражения имеет свойство lastIndex, который обновляется при запуске exec. Поэтому, когда вы выполняете регулярное выражение, например, «У меня тоже есть кошка и собака». lastIndex установлен в 12. При следующем запуске exec на том же объекте регулярного выражения он начинает искать индекс 12. Таким образом, вы должны сбросить свойство lastIndex между каждым прогоном.

+0

Ба, этот сайт слишком быстро для меня. +1 для SilentGhost :-) – Frode

+0

Вижу, спасибо за объяснение. – cpak

+6

Спасибо за объяснение! Это очень помогает, устанавливая 'myRe.lastIndex = 0;' для последующего использования. – Antony

4

У меня была аналогичная проблема с использованием/g только, и предлагаемое решение здесь не работало для меня в FireFox 3.6.8. Я получил свой скрипт, работающий с

var myRegex = new RegExp("my string", "g"); 

Я добавляю это на случай, если у кого-то другая проблема, с которой я справился.

15

две вещи:

  1. Указанная потребность сброса при использовании (глобальных) флаг g. Чтобы решить эту проблему, я рекомендовал просто назначить 0 члену lastIndex объекта RegExp. Это имеет лучшую производительность, чем разрушение и восстановление.
  2. Будьте осторожны, когда используйте ключевое слово in, чтобы пройти объект Array, поскольку это может привести к неожиданным результатам с некоторыми библиотеками. Иногда вам следует проверить что-то вроде 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>"); 
    } 
    } 
Смежные вопросы