2016-08-28 4 views
-3

у меня есть этот код:Javascript регулярного выражения не работает должным образом

<!DOCTYPE html> 
<html> 
<head> 
<script> 
words = ["hi2", "say3", "you1", "me1"], 

regex1 = /[\S]{2,3}[1|2|3]/g, 

window.word_text = function(){ 

    var data = document.getElementById("input").value.split(" ") 

    for (i = 0; i < data.length; i++){ 

     for (j = 0; j < words.length; j++){ 
      if (regex1.exec(data[i]) == words[j]){ 

       console.log("match"); 
      } 
      else{ 
       console.log("no match") 
      } 
     } 
    } 
} 
</script> 
</head> 

<body> 
<input id="input" type="text" onblur="word_text()"> 

</body> 
</html>  

Когда данные [я] хороший матч («hi2») инструкция не всегда выполняется так, как представляется, проблема с моим регулярным выражением , Обратите внимание, что он отлично работает без g (несколько совпадений), но мне это нужно, потому что в выражении if «hi2» будет заменен массивом вещами с двумя или тремя буквами, за которыми следуют 1, 2 или 3. Поэтому мне нужны мои данные [i], чтобы распознать «hi2say1» для соответствия «hi2» и «say1».

Большое вам спасибо за помощь!

+1

'exec' возвращает массив или нуль. Но ваша цель очень неясна. Можете ли вы построить фрагмент с определенным кодом и точно указать желаемый результат? См. Http://stackoverflow.com/help/mcve –

+0

Что такое 'data [i]'? Почему вы сравниваете строку с массивом? – GingerPlusPlus

+0

Видя, что '/ g' вызывает проблему, и вы говорите * не всегда *, кажется, что у вас возникают проблемы с тем, как' exec' обрабатывает последовательные совпадения. Обратите внимание, что 'regex1.exec' не будет давать одинаковый результат каждый раз при последовательных вызовах с одним и тем же вводом, если выражение имеет глобальный флаг. Трудно, однако, дать хороший ответ на то, что вы должны делать, от того, как формулируется ваш вопрос. [См. Раздел о последующих совпадениях здесь] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec) –

ответ

1

Если вы используете выражение с глобальным флагом, exec будет продвигаться через струну на каждом последующем вызове, и дают новые матчи. Каждый вызов будет выполнять поиск с начала предыдущего совпадения.

В какой-то момент вы достигнете последнего матча. Вызов exec на этом месте больше не найдет совпадений и вернет null. Выражения lastIndex флаг будет сброшен, а другой вызов exec будет перезапустить поиск с нуля:

regex1 = /[\S]{2,3}[1|2|3]/g 
 
var input = 'hi2say1'; 
 
for(var i = 0; i < 10; i++) 
 
    console.log(i, JSON.stringify(regex1.exec(input)));

Результат exec предназначен для итерироваться в то время как он не является нулевым, чтобы вы проверяете каждое последующее соответствие в глобальном выражении. Поскольку вы повторяете каждое слово, вам не нужно проверять каждое соответствие в выражении на каждой итерации - вы явно ищете одну фразу за раз. Это может быть достигнуто гораздо проще с помощью простого indexOf:

var words = ["hi2", "say3", "you1", "me1"]; 
 
var data = 'say1hi2abc a1hi2'.split(" "); 
 

 
for (i = 0; i < data.length; i++){ 
 
    for (j = 0; j < words.length; j++){ 
 
    if (data[i].indexOf(words[j]) >= 0){ 
 
     console.log("MATCH!", data[i], "does contain", words[j]); 
 
    } else { 
 
     console.log("No match.", words[j], "was not found in", data[i]); 
 
    } 
 
    } 
 
}

+0

Это ТОЧНО, что я искал, СПАСИБО! –

1

Ваша логика может быть упрощена. Глядя на код, вас действительно интересуют только точные совпадения с списком words, поэтому сделайте регулярное выражение, которое указывает только, может ли оно совпадение со словом не так полезно. Внутреннее сравнение, которое вы делаете, на самом деле не нуждается в регулярном выражении.

Изменение:

regex1.exec(data[i]) == words[j] 

To:

data[i] == words[j] 

... и он будет работать. Консоль покажет много «нет соответствия» и некоторого «совпадения».

Однако вы можете использовать регулярное выражение, чтобы сделать ваш код более эффективным, но он должен точно соответствовать только тому, что находится в списке слов. Вот как вы могли бы сделать это:

var words = ["hi2", "say3", "you1", "me1"], 
 
    regex1 = new RegExp('\\b(' + words.join('|') + ')\\b', 'g'), 
 
    input = document.getElementById("input"), 
 
    output = document.getElementById("output"); 
 

 
function word_text(){ 
 
    var data = input.value, 
 
     match = data.match(regex1); 
 
    if (match) { 
 
     output.textContent = "matches: " + match; 
 
    } 
 
    else{ 
 
     output.textContent = "no match"; 
 
    } 
 
} 
 

 
// link event handler, and run it now 
 
input.oninput = word_text; 
 
word_text();
Type here: <input id="input" style="width:100%" value="can hi2 this is a test for you1"> 
 
<div id="output"></div>

+0

Большое спасибо! Я забыл сказать, что вход может также быть чем-то вроде «hi2?», «Me1 *» или «hi2say3», вот что вызывает мои проблемы. –

+0

Итак, что вы хотите с этими входами? Будут ли они считаться матчи или нет? – trincot

+0

Да, они будут считаться спичками. –

Смежные вопросы