Intereting Posts
HTML5 и getUserMedia – запись аудио и сохранение на веб-сервер через определенное время Как отлаживать скрипты php на стороне сервера? В ситуации клиентская страница не отображает ответ Прикрепление файла в почтовом коде php нажмите новое значение для внутреннего массива mongodb – mongodb / php Итерирование результата xpath SimpleXml Правильное экранирование полей и параметров запроса при использовании PDO как реализовать поиск двух разных табличных данных? Symfony2 – Как проверить адрес электронной почты в контроллере Как установить драйвер mysqlnd с помощью MAMP? Я хочу добавить строковые данные до первого символа и после последнего символа добавление и удаление классов css на href Коллекция встроенных форм для Symfony 2 Многие для многих Некоторые символы в CSV-файле не читаются во время PHP fgetcsv () Ковариация типов параметров в специализациях Wamp server: изменение httpd.conf для apache?

регулярное выражение, не совпадающее из-за повторной группы захвата, а не захвата повторяющейся группы

У меня есть следующее regexp:

/(?:[\[\{]*)(?:([AG\-][^AG\]\}]*)+)(?:[\]\}]*)/ 

со следующим выражением:

 {A''BsCb} 

Я ожидаю 3 согласованных результата

 A'' Bs Cb 

но тестирование на https://regex101.com/ дает мне последнее совпадение Cb и говорит мне, что группа повторного захвата будет захватывать только последнюю итерацию, помещая группу захвата вокруг повторяющейся группы.

Я думал, это было то, что я сделал! Я думал, что понял проблему, описанную здесь http://www.regular-expressions.info/captureall.html Следовательно, скобки за пределами моего + с группой захвата внутри.

Но либо это слишком поздно, либо мне нужен кто-то, кто головой, не взорвется при упоминании regexp, чтобы показать мне, где я ошибся.

Вы пытаетесь сопоставить повторяющиеся группы захвата и получать снимки. Это невозможно с PHP регулярным выражением PCRE.

Вы можете сделать так, чтобы вы либо извлекли все подстроки {...} / [...] , обрезали их из скобок и использовали простое [AG-][^AG]* regex, или добавили \G оператора и сделать ваше регулярное выражение неподъемным, но работающим как оригинальное.

Решение 1

 /(?:[[{]*|(?!\A)\G)\K[AG-][^AG\]}]*/ 

См. Демо-версию regex . Примечание: это регулярное выражение не проверяет закрытие ] или } , но его можно добавить с положительным взглядом.

  • (?:[[{]*|(?!\A)\G) – соответствует значению [ или { , ноль или более, или конечное местоположение предыдущего успешного совпадения
  • \K – опускает текст, сопоставленный до сих пор
  • [AG-] – буквы от A до G и a -
  • [^AG\]}]* – ноль или более символов, отличных от A до G и кроме ] и } .

См. Демонстрацию PHP .

Решение 2

 $re = '/(?|{([^}]*)}|\[([^]]*)])/'; $str = "{A''BsCb}"; $res = array(); preg_match_all($re, $str, $m); foreach ($m[1] as $match) { preg_match_all('~[AG-][^AG]*~', $match, $tmp); $res = array_merge($tmp, $res); } print_r($res); 

См. Демонстрацию PHP

Регулярное выражение (?|{([^}]*)}|\[([^]]*)]) Соответствует строкам типа {...} или [...] (но не {...] или [...} ) и фиксирует содержимое между скобками в группу 1 (поскольку группа сброса ветвей (?|...) сбрасывает идентификаторы групп в каждой ветке). Тогда все, что нам нужно, это захватить то, что нам нужно, с более последовательным регулярным выражением '~[AG-][^AG]*~' .

Вы можете получить его с помощью этого шаблона с preg_match_all в элементе 0:

 ~ (?: \G (?!\A) # contiguous to previous match, but not at the start of the string | { (?=[^}]* }) # start with { and check if a closing bracket follows | \[ (?=[^]]* ]) # the same for square bracket ) \K # start the match result here [AG] [^]AG}]* ~xS 

демонстрация

Вы уже поняли это. Что касается комментария @ sln, нет никакого способа собрать каждое сингулярное совпадение в одной или разных группах захвата, повторяя группу в PCRE, которая является ароматом регулярного выражения PHP. В этом случае фиксируется только последнее совпадение.

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

 $array = array_filter(preg_split("~(?=[AG])~", trim("{A''BsCb}", '[{}]'))); 

Regex:

 (?=[AG]) # Positive lookahead to find next character be one from character class 

Это регулярное выражение будет соответствовать всем аналогичным позициям для вывода правильных данных по split:

 array(3) { [1]=> string(3) "A''" [2]=> string(2) "Bs" [3]=> string(2) "Cb" } 

Демо-версия