Обновление / Примечание:
Я думаю, что я, вероятно, ищу, чтобы получить захват группы в PHP.
- Regex сопоставляет img-тег с определенным классом атрибутов
- Найти всю строку, содержащую слово с регулярными выражениями php
- регулярное выражение find-and-replace-in-html не выполняется
- Правило .htaccess для многоязычного сайта
- Regex соответствует только определенным символам, которым предшествует пробел или ничего (начало строки)
- php regex - <b>
Ссылка: регулярные выражения PCRE с использованием подпрограмм named pattern.
(Внимательно прочитайте:)
У меня есть строка, содержащая переменное число сегментов (упрощенная):
$subject = 'AA BB DD '; // could be 'AA BB DD CC EE ' as well
Теперь я хотел бы совместить сегменты и возвращать их через массив совпадений:
$pattern = '/^(([az]+) )+$/i'; $result = preg_match_all($pattern, $subject, $matches);
Это вернет только последнее совпадение для группы захвата 2: DD
.
Есть ли способ, с помощью которого можно получить все подшаблоны ( AA
, BB
, DD
) с одним выполнением регулярных выражений? Не подходит ли preg_match_all
для этого?
Оба параметра $subject
и $pattern
упрощаются. Естественно, что с таким общим списком AA
, BB
, .. намного легче извлекать с другими функциями (например, explode
) или с изменением $pattern
.
Но я специально спрашиваю, как вернуть все подгруппы в соответствие с preg preg_...
-семейством функций.
Для реального жизненного случая представьте, что у вас есть несколько (вложенных) уровней варианта количества матчей подшаблонов.
Это пример в псевдокоде, чтобы описать немного фона. Представьте себе следующее:
Регулярные определения токенов:
CHARS := [az]+ PUNCT := [.,!?] WS := [ ]
$subject
get tokenken на основе этих. Токенизация хранится внутри массива токенов (тип, смещение, …).
Затем этот массив преобразуется в строку, содержащую один символ для токена:
CHARS -> "c" PUNCT -> "p" WS -> "s"
Так что теперь можно запускать регулярные выражения на основе токенов (а не классов символов и т. Д.) В индексе строки потока токенов. Например
regex: (cs)?cp
для выражения одной или нескольких групп символов, за которыми следует пунктуация.
Поскольку теперь я могу выразить самоопределяемые токены как регулярное выражение, следующим шагом было построение грамматики. Это всего лишь пример, это своего рода стиль ABNF:
words = word | (word space)+ word word = CHARS+ space = WS punctuation = PUNCT
Если я сейчас скомпилирую грамматику для слов в (маркерное) регулярное выражение, я бы хотел, чтобы все подгруппы соответствовали каждому слову .
words = (CHARS+) | ( (CHARS+) WS )+ (CHARS+) # words resolved to tokens words = (c+)|((c+)s)+c+ # words resolved to regex
Я мог бы написать код до этого момента. Затем я столкнулся с проблемой, что совпадения подгрупп содержали только их последнее совпадение.
Поэтому у меня есть возможность либо самостоятельно создать автоматы для грамматики (что я хотел бы предотвратить, чтобы сохранить общие грамматические выражения), либо несколько сделать preg_match для меня каким-то образом, поэтому я могу это сэкономить.
Это в основном все. Вероятно, теперь понятно, почему я упростил вопрос.
Связанный:
Попробуй это:
preg_match_all("'[^ ]+'i",$text,$n);
$n[0]
будет содержать массив всех непространственных символов в тексте.
Изменить: с подгруппами:
preg_match_all("'([^ ]+)'i",$text,$n);
Теперь $n[1]
будет содержать совпадения подгрупп, которые точно совпадают с $n[0]
. На самом деле это бессмысленно.
Пример Edit2: вложенные подгруппы:
$test = "Hello I'm Joe! Hi I'm Jane!"; preg_match_all("/(H(ello|i)) I'm (.*?)!/i",$test,$n);
И результат:
Array ( [0] => Array ( [0] => Hello I'm Joe! [1] => Hi I'm Jane! ) [1] => Array ( [0] => Hello [1] => Hi ) [2] => Array ( [0] => ello [1] => i ) [3] => Array ( [0] => Joe [1] => Jane ) )
Вы не можете извлечь подшаблоны, потому что способ, которым вы написали свое регулярное выражение, возвращает только одно совпадение (используя одновременно ^
и $
и +
на основном шаблоне).
Если вы напишете это так, вы увидите, что ваши подгруппы правильно там:
$pattern = '/(([az]+) )/i';
(у этого все еще есть ненужный набор круглых скобок, я просто оставил его там для иллюстрации)
Есть ли способ, чтобы я мог получить все совпадения (AA, BB, DD) с одним выполнением регулярных выражений? Не подходит ли preg_match_all для этого?
Ваше текущее регулярное выражение похоже на вызов preg_match (). Попробуйте это вместо этого:
$pattern = '/[az]+/i'; $result = preg_match_all($pattern, $subject, $matches);
По комментариям, рубиновое регулярное выражение, о котором я упоминал:
sentence = %r{ (?<subject> cat | dog ){0} (?<verb> eats | drinks ){0} (?<object> water | bones ){0} (?<adjective> big | smelly ){0} (?<obj_adj> (\g<adjective>\s)? ){0} The\s\g<obj_adj>\g<subject>\s\g<verb>\s\g<opt_adj>\g<object> }x md = sentence.match("The cat drinks water"); md = sentence.match("The big dog eats smelly bones");
Но я думаю, вам понадобится lexer / parser / tokenizer, чтобы делать то же самое в PHP. : – |
Аналогичная тема: Получите повторные совпадения с preg_match_all ()
Проверьте выбранный ответ плюс мой может быть полезным Я буду дублировать там:
С http://www.php.net/manual/en/regexp.reference.repetition.php :
Когда повторный подзапрос захвата повторяется, полученное значение представляет собой подстроку, которая соответствует последней итерации.
Я лично сдаюсь и собираюсь сделать это за 2 шага.
редактировать
Я не понимал, о чем вы изначально просили. Вот новое решение:
$result = preg_match_all('/[az]+/i', $subject, $matches); $resultArr = ($result) ? $matches[0] : array();
Как насчет:
$str = 'AA BB CC'; $arr = preg_split('/\s+/', $str); print_r($arr);
вывод:
( [0] => AA [1] => BB [2] => CC )
Возможно, я неправильно понял, что вы описываете. Вы просто ищете шаблон для групп букв с пробелом между ними?
// any subject containing words: $subject = 'AfdfdfdA BdfdfdB DdD'; $subject = 'AA BB CC'; $subject = 'Af df dfdA Bdf dfdB DdD'; $pattern = '/(([az]+)\s)+[az]+/i'; $result = preg_match_all($pattern, $subject, $matches); print_r($matches); echo "<br/>"; print_r($matches[0]); // this matches $subject echo "<br/>".$result;
Да, ваше право ваше решение с помощью preg_match_all
preg_match_all является рекурсивным, поэтому не используйте start-with ^
и end-with $
, так что preg_match_all
помещает все найденные шаблоны в массив.
Каждая новая пара скобок добавит новые массивы, указывающие разные совпадения
использовать ?
для дополнительных совпадений
Вы можете разделить разные группы шаблонов, сообщаемых с помощью скобки ()
чтобы попросить группу найти и добавить в новый массив (можно разрешить подсчет совпадений или классифицировать каждое соответствие из возвращаемого массива)
Позвольте мне попытаться понять ваш вопрос, чтобы мой ответ соответствовал тому, что вы просите.
Ваш $subject
не является хорошим примером того, что вы ищете?
Вам нужен предварительный поиск, чтобы разделить то, что вы предоставили в $subject
на 4 категории , слова , символы , знаки препинания и пробелы ? и как насчет чисел ?
Также вы бы хотели, чтобы возвращаемые совпадения соответствовали смещениям совпадений?
$subject = 'aa.bb cc.dd EE FFF,GG';
лучше подходит реальная жизнь?
Я возьму ваш основной пример в $subject
и сделаю его работу, чтобы дать вам именно то, что вы попросили.
Так что вы можете отредактировать свой $subject
чтобы я лучше поместил все случаи, которые вы хотите сопоставить
Оригинал '/^(([az]+) )+$/i';
Держите меня в курсе, вы можете проверить свои регулярные выражения здесь http://www.spaweditor.com/scripts/regex/index.php
/([az])([az]+)/i
AA BB DD CD
Array ( [0] => Array ( [0] => AA [1] => BB [2] => DD [3] => CD ) [1] => Array ( [0] => A [1] => B [2] => D [3] => C ) [2] => Array ( [0] => A [1] => B [2] => D [3] => D ) )