2009-11-26 2 views
0

Возьмем следующий код:группировка перед положительным не соответствует 'назад

$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 и каждый Р в пределах $ цели (таким образом PREG_OFFSET_CAPTURE). Шаблон работает для Ps, но он не соответствует ни одной из названных групп «ruleName» или «funcName».

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

Спасибо.

ответ

1

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

  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))/ 
+0

Действительно, спасибо, исправлено. В любом случае это не влияет на то, что он не работает. – Flavius