2017-01-11 6 views
0

не удается получить, почему это регулярное выражение (regex101)Повторные захвата группы PCRE

/[\|]?([a-z0-9A-Z]+)(?:[\(]?[,][\)]?)?[\|]?/g 

захватывает все входные, в то время как это (regex101)

/[\|]+([a-z0-9A-Z]+)(?:[\(]?[,][\)]?)?[\|]?/g 

захватывает только |Func

Введите строку is |Func(param1, param2, param32, param54, param293, par13am, param)|

Также как я могу сопоставить повторяющуюся группу захвата в обычном режиме? Например. я REGEX

/\(\(\s*([a-z\_]+){1}(?:\s+\,\s+(\d+)*)*\s*\)\)/gui 

И входная строка ((string , 1 , 2)).

Regex101 говорит, что «повторная группа захвата будет захватывать только последнюю итерацию. Поместите группу захвата вокруг повторяющейся группы, чтобы захватить все итерации ...». Я попытался следовать этому совету, но мне это не помогло.

+1

См. ['\ | + ([A-z0-9A-Z] +) (?: \ (? (\ W + (?: \ S *, \ s * \ w +) *) \)?) \ |? '] (https://regex101.com/r/ypZGcv/3). Вы не можете захватить все повторные захваты с помощью PCRE, вы можете сопоставить их с использованием регулярного выражения '\ G'. См. ['(?: \ G (?! \ A) \ s *, \ s * | \ | + ([a-z0-9A-Z] +) \() \ K \ w +'] (https://regex101.com/r/ypZGcv/4). –

+0

Не знал, что я не могу захватить все это одним вызовом с помощью PCRE. Теперь я понимаю, поэтому regex101 просил меня захватить повторяющуюся группу, чтобы она соответствовала ей один матч. Большое спасибо за вашу помощь! – user2890234

ответ

1

Regex /[\|]+([a-z0-9A-Z]+)(?:[\(]?[,][\)]?)?[\|]?/g не соответствует, потому что вы не определили шаблон, соответствующий словам внутри скобок. Вы можете исправить это как \|+([a-z0-9A-Z]+)(?:\(?(\w+(?:\s*,\s*\w+)*)\)?)?\|?, но все значения в круглых скобках будут сопоставлены в одну группу, которую вам придется разбить позже.

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

Что вы можете сделать, это получить взаимные совпадения с preg_match_all, фиксируя начальный разделитель.

Таким образом, чтобы соответствовать второй строке, вы можете использовать

(?:\G(?!\A)\s*,\s*|\|+([a-z0-9A-Z]+)\()\K\w+ 

the regex demo См.

Детали:

  • (?:\G(?!\A)\s*,\s*|\|+([a-z0-9A-Z]+)\() - либо конец предыдущего матча (\G(?!\A)) и запятой, приложенном 0+ (\s*,\s* пробелами) или 1+ | символов (\|+), а затем с 1 + буквенно-цифровые символы (захватывается в 1-й группе, ([a-z0-9A-Z]+)) и ( символ (\()
  • \K - опустить текст, совпадающий до сих пор
  • \w+ - 1 + слово символы.
+1

Я попытался передать второе regexp в качестве параметра 'preg_match_all', и это именно то, что мне нужно.Кроме того, сопоставление первого регулярного выражения и синтаксического анализа родительского захвата кажется гораздо более ясным, но для этого требуется, по крайней мере, +1 preg_match, поэтому я бы выбрал второй вариант. Спасибо за отличное объяснение! – user2890234

+1

Да, только что поддержал ваш ответ, когда получил требуемый рейтинг для этого действия :) Пару часов назад у меня недостаточно рейтинга для увеличения – user2890234

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