группировка перед положительным взглядом сзади не соответствует
Вопрос
Возьмите следующий код:
$target = 'NAME FUNC LPAREN P COMMA P COMMA P RPAREN';
//$target = 'NAME FUNC LPAREN P RPAREN';
//$target = 'NAME FUNC LPAREN RPAREN';
$pattern = '/(?P<ruleName>NAME )?(?P<funcName>FUNC )?(?:(?<=LPAREN)(?: (?P<arg1>P))|(?P<args>P)(?=(?: RPAREN)|(?: COMMA)))/';
preg_match_all($pattern,$target,$matches,PREG_OFFSET_CAPTURE|PREG_PATTERN_ORDER);
Мне нужно получить позицию NAME, FUNC и каждого P внутри $ target (таким образом, PREG_OFFSET_CAPTURE).Шаблон работает для Ps, но он не соответствует ни одной из именованных групп "RuleName" или "funcName".
Что я упускаю из виду?
Спасибо.
Решение
Я думаю, что нашел причину.
- Ваши именованные обратные ссылки необязательны.
- Если они совпадают (а с первой попытки это так и есть), то движок регулярных выражений находится слева от "LPAREN".
- Следующий маркер, которому механизм регулярных выражений пытается сопоставить, - это символ пробела.Это происходит потому, что выражение lookbehind
(?<=LPAREN)
не использует символы в строке. - Это не может соответствовать пробелу, потому что там есть буква "Л".
- Механизм регулярных выражений отбрасывает необязательные совпадения из 2.и продолжается до тех пор, пока не найдет следующее место.
- Он совпадает и продолжает совпадать с тех пор, захватывая все
P
s.Но от названных групп пришлось отказаться, чтобы это сработало.
Я не уверен, зачем вам нужен взгляд сзади.Как насчет
/(?P<ruleName>NAME )?(?P<funcName>FUNC )?(?:LPAREN )(?:(?P<arg1>P))|(?P<args>P)(?=(?: RPAREN)|(?: COMMA))/
Не связан с StackOverflow