Страницы

Поиск по вопросам

Показаны сообщения с ярлыком match. Показать все сообщения
Показаны сообщения с ярлыком match. Показать все сообщения

вторник, 28 января 2020 г.

Поведение match в JavaScript

#регулярные_выражения #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 (с урезанным функционалом). подробней о механизмах подробней о синтаксисе попробовать (подебажить)

вторник, 31 декабря 2019 г.

Создание массивов из текста

#php #регулярные_выражения #lua #match


У меня например есть строка

s = "Hello, world! {255,0,0}Привет, мир! {155,55,0}How are {100,3,5you?"


Мне нужно разделить с помощью выражений, а именно функцией string.gmatch, на массив
который будет вмещать в себе масивы с цвета R, G, B и самой строки. То есть чтобы в
результате я получил массив:

arr[1] = {0, 0, 0, "Hello, world! "}
// Из-за того что в начале строки нет кода цвета, то по умолчанию ставить цвет по нулям

arr[2] = {255, 0, 0, "Привет, мир! "}

arr[3] = {155, 55, 0, "How are {100,3,5you?"}
// "How are {100,3,5you?" - именно так, по скольку неправильно сформирован код цвета,
также если будет например буква внутри {100,3Я,5}, то это также все пойдет в строку


Вот что у меня получилось написать на LUA:

arr = {}
s = "Hello, world! {255,0,0}Привет, мир! {155,55,0}How are {100,3,5you?"
for k, v in string.gmatch(s, "{(%d+,%d+,%d+)}([^{]*)") do
    local r, g, b = string.match(k, "(%d+),(%d+),(%d+)")
    table.insert(arr, {r, g, b, v})
end


В результате получаю массив:

arr[1] = {255, 0, 0, "Привет, мир! "}
arr[2] = {155, 55, 0, "How are "}


Но меня это не устраивает:

1) нет части строки, в которой не указан цвет, то есть нет массива 
arr[1] = {0, 0, 0, "Hello, world! "}

2) Обрезает до следующего символа {, а нужно чтобы обрезало до комбинации цвета

Как по-другому это реализовать (но в простом варианте, то есть так, чтобы не было
большой нагрузки), или хотя бы как например такое реализовать в PHP, а я бы попытался
уже как-то перевести на LUA
    


Ответы

Ответ 1



Может кто-то знает как по другому это реализовать (но в простом варианте, тоесть так чтобы не было большой нагрузки), или хотя бы как например такое реализовать в PHP Вот такая реализация: $s = "Hello, world! {255,0,0}Привет, мир! {155,55,0}How are {100,3,5you?"; $res = []; // Делим предложение $words = explode(" {", $s); foreach($words as $k => $w){ // цвета R, G, B preg_match('/(\d+,\d+,\d+)\}?/', $w, $match); if(!empty($match)){ // Только текст без цветов R, G, B preg_match('/[^(\d+,\d+,\d+)\}?].+/', $w, $not_m); $res[] = [$match[1], $not_m[0]]; }else{ $res[] = ['0,0,0', $w]; } } print_r($res); Получаем результат: Array ( [0] => Array ( [0] => 0,0,0 [1] => Hello, world! ) [1] => Array ( [0] => 255,0,0 [1] => Привет, мир! ) [2] => Array ( [0] => 155,55,0 [1] => How are ) [3] => Array ( [0] => 100,3,5 [1] => you? ) )

Ответ 2



// TEXT $text = "Hello, world! {255,0,0}Привет, мир! {155,55,0}How are {100,3,5you?"; // PARSE preg_match_all("#{(\d+,\d+,\d+)}#Uu", $text, $matches, PREG_OFFSET_CAPTURE|PREG_SET_ORDER); // VAR $result = []; $color = '0,0,0'; $offset = 0; // EACH foreach ($matches as $key => $value) { $text_sub = substr($text, $offset, ($value[0][1] - $offset)); if (mb_strlen($text_sub) > 0) { $result[] = array_merge(explode(',', $color), [$text_sub]); } $offset = $value[0][1] + mb_strlen($value[0][0]); $color = $value[1][0]; } // LAST $text_sub = substr($text, $offset); if (mb_strlen($text_sub) > 0) { $result[] = array_merge(explode(',', $color), [$text_sub]); } var_dump($result); Может и костыльно, но то что вам нужно, делает.

Ответ 3



Вот вам вариант без циклов: $text = '{100,0,0}Hello, world! {255,0,0}Привет, мир! {155,55,0}How are {100,3,5you?'; $str = array_filter(preg_split('~{(\d+),(\d+),(\d+)}~', $text)); preg_match_all('~(.+?){~', $text, $matches, PREG_SET_ORDER); $result = array_map(function ($x, $y) { return (!preg_match_all('/(\d+),(\d+),(\d+)/', $x[0], $match)) ? [0, 0, 0, $y] : [$match[1][0], $match[2][0], $match[3][0], $y]; }, $matches, $str); print_r($result);

Ответ 4



Вот примерно так получилось: s = "Hello, world! {255,0,0}Привет, мир! {155,55,0}How are {100,3,5you?" s = s .. "\n" -- вынужденная мера, обозначим конец строки arr = {} local arr = {{0,0,0,""}} local i=1 for case in s:gmatch ("(.-[%c}])") do -- print ( case ) local text = case:match("(.+){") local r, g, b = case:match( "{(%d+),(%d+),(%d+)}") if r and g and b then arr[i+1] = {r,g,b,""} else text = case end arr[i][4] = text i=i+1 end -- test for k,v in pairs(arr) do print(k, v[1], v[2], v[3], v[4]) end результат: 1 0 0 0 Hello, world! 2 255 0 0 Привет, мир! 3 155 55 0 How are {100,3,5you?

понедельник, 8 июля 2019 г.

Игнорировать \s \t \n javascript регулярные выражения

Подскажите, пожалуйста, как игнорировать строку, где есть пробелы (\s), табуляции (\t), переносы строк (
) и нет никакого другого символа?


Ответ

Если вы хотите реализовать проверку всей строки на пробельные символы, то можно обойтись и без регулярных выражений с помощью trim()
var s = "\u0020\u00A0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\t"; console.log("Исходная строка: '", s, "'"); if (s.trim() === '') { console.log('Строка содержит только пробельные символы!'); }
Если вам обязательно нужно именно регулярное выражение, используйте решение Other
Если необходимо проверить, состоит ли строка только из конкретных пробельных символов, например, знака табуляции, перевода каретки и перехода на новую строку, можно использовать символьный класс:
if (/^[\t
]+$/.test(s)) { /* строка содержит только \t,
и/или
*/ }
Тут
^ - начало строки [\t
]+ - один и более знаков табуляции, перевода каретки и перехода на новую строку $ - конец строки.
Класс [\t
] можно заменить на \s, если необходимо сделать проверку на все пробельные символы.

вторник, 9 октября 2018 г.

Найти между несколькими скобками значения JavaScript

Здравствуйте. Пытаюсь вытащить значения, которые лежат в строке между скобками. Пока продвинулся не далеко. Вот что имею:
'{1}{2}{3}{4}'.match(/\{(.*)\}/)[1]; // 1}{2}{3}{4
Не могу понять почему выводится, 1}{2}{3}{4, когда я написал, чтоб выводилось всё, что находится между фигурными. В чем ошибка?


Ответ

Потому что спецсимвол (точка) равнозначен любому символу, включая скобки, и выборка происходит как раз согласно вашему выражению: все символы от самой первой открывающей скобки, до последней закрывающей.
Вы можете модифицировать ваше регулярное выражение, чтобы выбрать "первое значение, заключенное в скобки" (не обязательно число), указав вместо исключение закрывающей скобки [^\}]
'{1}{2}{3}{4}'.match(/\{([^\}]*)\}/)[1] // 1
Однако, если вам нужно получить массив всех чисел из строки строго данного формата, куда проще сделать следующим образом:
'{1}{2}{3}{4}'.match(/\d+/g); // ["1", "2", "3", "4"]
Регулярные выражения Online regex tester and debugger