agrupación frente a una mirada positiva detrás no coincidente
Pregunta
Tome el siguiente código:
$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);
Necesito obtener la posición de NAME, FUNC y cada P dentro del objetivo $ (por lo tanto, PREG_OFFSET_CAPTURE). El patrón funciona para Ps, pero no coincide con ninguno de los grupos nombrados & Quot; ruleName & Quot; o " funcName " ;.
¿Qué me estoy perdiendo?
Gracias.
Solución
Creo que he encontrado la razón.
- Sus referencias posteriores son opcionales.
- Si coinciden (y en el primer intento lo hacen), entonces el motor de expresiones regulares se encuentra a la izquierda de " LPAREN " ;.
- La siguiente ficha que el motor de expresiones regulares intenta hacer coincidir es un carácter de espacio. Esto se debe a que la expresión de retrospectiva
(?<=LPAREN)
no consume caracteres en la cadena. - No puede coincidir con el espacio porque hay una L
- El motor regex descarta las coincidencias opcionales de 2. y continúa hasta que encuentra el siguiente espacio.
- Coincide y sigue coincidiendo desde entonces, capturando todos los
P
s. Pero los grupos nombrados tuvieron que ser abandonados para que esto funcione.
No estoy seguro de por qué necesitas mirar atrás. ¿Qué tal
/(?P<ruleName>NAME )?(?P<funcName>FUNC )?(?:LPAREN )(?:(?P<arg1>P))|(?P<args>P)(?=(?: RPAREN)|(?: COMMA))/
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow