группировка перед положительным взглядом, за не совпадающим - PullRequest
0 голосов
/ 26 ноября 2009

Возьмите следующий код:

$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".

Чего мне не хватает?

Спасибо.

1 Ответ

1 голос
/ 26 ноября 2009

Я думаю, что нашел причину.

  1. Ваши именованные обратные ссылки необязательны.
  2. Если они совпадают (и с первой попытки это делают), то механизм регулярных выражений стоит слева от "LPAREN".
  3. Следующий токен, который пытается найти движок регулярных выражений, - это пробел. Это связано с тем, что выражение lookbehind (?<=LPAREN) не использует символы в строке.
  4. Это не может соответствовать пробелу, потому что есть L
  5. Механизм регулярных выражений отбрасывает необязательные совпадения из 2. и продолжается до тех пор, пока не найдет следующий пробел.
  6. Это соответствует и продолжает соответствовать с тех пор, захватывая все P s. Но названные группы должны были быть оставлены, чтобы это работало.

Я не уверен, зачем вам нужен взгляд сзади. Как насчет

/(?P<ruleName>NAME )?(?P<funcName>FUNC )?(?:LPAREN )(?:(?P<arg1>P))|(?P<args>P)(?=(?: RPAREN)|(?: COMMA))/
...