#регулярные_выражения #match #javascript
Всем привет. Снова немного о регулярных выражениях в JS. Я ожидаю, что код: 'aabb'.match(/a.*b/g); , вернет мне массив: ['aab', 'aabb', 'ab', 'abb']; Почему он возвращает массив только с одним элементом? ['aabb'] Разве str.match(RegExp); не должен возвращать массив всех совпадений по регулярному выражению?
Ответы
Ответ 1
Надо объединить возможности регулярных выражений, такие как жадный и ленивый поиск, захват подстроки в блоке просмотра и глобальный модификатор: re = /(?=(a.*?b))(?=(a.*b))/g; s = 'aabb'; arr = []; while ((m=re.exec(s)) !== null) { if (m.index === re.lastIndex) { re.lastIndex++; } if (m[1] && arr.indexOf(m[1]) === -1) arr.push(m[1]); if (m[2] && arr.indexOf(m[2]) === -1) arr.push(m[2]); } document.write(JSON.stringify(arr)); В данном случае, выражение при нахождении совпадения вернет пустой результат в m[0], но благодаря подмаскам в m[1] и m[2] будут извлечены захваченные подстроки. Так как эти подстроки могут быть идентичны, необходима проверка существующих элементов. ОТВЕТ НА КОММЕНТАРИЙ: Для поиска всех пермутаций на основе любого шаблона, можно воспользоваться следующим кодом. Его особенность: собираем все совпадения, а потом последовательно определяем, есть ли совпадения внутри совпадения. Таким образом, нет необходимости проверять абсолютно все пермутации входной строки. function permRegex(re_str, s) { var arr = []; // Все наши пермутации var caps = []; // Все начальные совпадения (caps) var re = RegExp(re_str, "g"); // Глобальное выражение для caps while ((m = re.exec(s)) !== null) { // Ищем... caps.push(m[0]); // и добавляем совпадение в caps } var re2 = RegExp("^" + re_str + "$"); // Создаем неглобальное выражение для проверки на совпадение ЦЕЛОЙ строки for (var c=0; c"; // "aabb" => ["aabb", "aab", "abb", "ab"] document.getElementById("a1").innerHTML += JSON.stringify(permRegex("a.*b", "aabbb")) + "
"; // "aabbb" => ["aabbb", "aabb", "aab", "abbb", "abb", "ab"] document.getElementById("a1").innerHTML += JSON.stringify(permRegex("е.*т", "А где енот?")); // "е.*т", "А где енот?" => ["е енот", "енот"] function permRegex(re_str, s) { var arr = []; // Все наши пермутации var caps = []; // Все начальные совпадения (caps) var re = RegExp(re_str, "g"); // Глобальное выражение для caps while ((m = re.exec(s)) !== null) { // Ищем... caps.push(m[0]); // и добавляем совпадение в caps } var re2 = RegExp("^" + re_str + "$"); // Создаем неглобальное выражение для проверки на совпадение ЦЕЛОЙ строки for (var c=0; c"; // "aabb" => ["aabb", "aab", "abb", "ab"] document.getElementById("a1").innerHTML += JSON.stringify(permRegex("a.*b", "aabbb")) + "
"; // "aabbb" => ["aabbb", "aabb", "aab", "abbb", "abb", "ab"] document.getElementById("a1").innerHTML += JSON.stringify(permRegex("е.*т", "А где енот?")); // "е.*т", "А где енот?" => ["е енот", "енот"] $( "#run" ).on( "click", function() { $( "#a1" ).html( JSON.stringify(permRegex( $( "#regex" ).val(), $( "#text" ).val() ) ) ); } );
Ответ 2
Чтобы получить все возможные подходящие подстроки, надо их вручную перебрать и каждую проверить на полное совпадение с выражением. Соответственно, к выражению надо добавить признаки начала и конца строки, но так, чтобы не сбились группы внутри. function doit(r, s) { var res = [], cur; r = RegExp('^(?:' + r.source + ')$', r.toString().replace(/^[\s\S]*\/(\w*)$/, '$1')); r.global = false; for (var q = 0; q < s.length; ++q) for (var w = q; w <= s.length; ++w) if (r.test(cur = s.substring(q, w))) res.push(cur); return res; } $( "#run" ).on( "click", function() { $( "#a1").text( JSON.stringify( doit( eval( $( "#regex" ).val() ), $( "#text" ).val() ) ) ); } ); doit( /a.*b/g, 'aabb' ) // Array [ "aab", "aabb", "ab", "abb" ] doit( /a(.|cc)/g, 'acc' ) // Array ["ac","acc"]
Ответ 3
Вы описали почти правильный ожидаемый результат для DFA механизма регулярных выражений (возможно вы перешли с другого языка где используется диалект регулярок с использованием этого устарелого механизма), но вот javaScript (а точнее браузеры) поддерживает NFA механизм, реализуется с помощью библиотеки PCRE (с урезанным функционалом). подробней о механизмах подробней о синтаксисе попробовать (подебажить)
Комментариев нет:
Отправить комментарий