2011-10-19 19 views
5

Todavía estoy aprendiendo mucho sobre PHP y la alteración de cadenas es algo que me interesa. He usado preg_match antes para cosas como validar una dirección de correo electrónico o simplemente buscar consultas.¿Cómo preg_match_all() procesa cadenas?

Acabo de salir de esta publicación What's wrong in my regular expression? y tenía curiosidad por saber por qué la función preg_match_all produce 2 cadenas, 1 w/algunos de los caracteres eliminados y luego el otro con el resultado deseado.

Por lo que entiendo acerca de la función es que va sobre la cadena carácter por carácter utilizando el RegEx para evaluar qué hacer con él. ¿Podría este RegEx se ha estructurado de tal manera que omitir la primera entrada de matriz y solo producir el resultado deseado?

y por lo que no tiene que ir al otro hilo

$str = 'text^name1^Jony~text^secondname1^Smith~text^email1^example- 
     [email protected]~'; 

preg_match_all('/\^([^^]*?)\~/', $str, $newStr); 

for($i=0;$i<count($newStr[0]);$i++) 
{ 
    echo $newStr[0][$i].'<br>'; 
} 

echo '<br><br><br>'; 

for($i=0;$i<count($newStr[1]);$i++) 
{ 
    echo $newStr[1][$i].'<br>'; 
} 

Esta es la salida

^~ Jony
^~ Smith
^[email protected]~


Jony
Smith
[email protected]

Tengo curiosidad por saber si el motivo de 2 entradas de matriz fue debido a la sintaxis original de la cadena o si es la respuesta de procesamiento normal de la función. Lo siento si esto no debería estar aquí, pero tengo mucha curiosidad sobre cómo funciona esto.

gracias, Brodie

+0

La salida siempre contendrá la coincidencia completa y una entrada para cada grupo de captura en su expresión. –

+0

No es una respuesta, pero interesante notar aquí es el indicador 'PREG_SET_ORDER', que devolverá una lista de resultados más simple. Y aunque no puede eliminar la entrada de matriz '[0]' para la coincidencia completa, puede quitar su contenido usando '\ K' en la expresión regular. – mario

Respuesta

2

Es un comportamiento estándar para preg_match y preg_match_all - la primera cadena de la matriz "valores coincidentes" es la cadena COMPLETA capturada por el patrón de expresión regular. Los valores de matriz posteriores son los "grupos de captura", cuya existencia depende de la ubicación/posición de los pares () en el patrón de expresión regular.

En el caso de su expresión regular, /\^([^^]*?)\~/, la cadena coincidente completa sería

^ Jony ~ 
|  |  | 
^ ([^^]*?) ~ -> $newstr[0] = ^Jony~ 
       -> $newstr[1] = Jony (due to the `()` capture group). 
+0

Ah lo entiendo, así que lo primero que hace es buscar el texto que comienza con w/^ y termina con ~ y luego la segunda expresión en() toma todo después de^menos el ~. Creo que la curiosidad se aprovecha de mí, si [^^] *? le dice que agarre el texto después de '^' ¿por qué entonces no agarra el '~'? – Brodie

+0

Sí, pero el '~' no está dentro de su grupo de captura, por lo que solo aparecerá en la sección '[0]'. Puede considerar que el patrón regex completo es un grupo de captura, de modo que esa captura virtual se almacena en '[0]', y luego cualquier captura que cree explícitamente con '()' entre [1], [2], etc ... –

+0

'[^^] *?' se traduce en 'tantos caracteres (*, '0 o más') que NO son^([^^]), de manera no codiciosa (?). –

0

[0] contiene toda partido, mientras que [1] sólo una parte (la parte que desea extraer) ... Usted puede hacer var_dump($newStr) para ver la estructura de matriz, lo descubrirán .

$str = 'text^name1^Jony~text^secondname1^Smith~text^email1^example- 
     [email protected]~'; 

preg_match_all('/\^([^^]*?)\~/', $str, $newStr); 

$newStr = $newStr[1]; 
foreach($newStr as $key => $value) 
{ 
    echo $value."\n"; 
} 

Esto dará como resultado (expresión resultado raro, no han modificado) en ...

Jony 
Smith 
example- 
     [email protected] 
1

Como los manual estados, esto es el resultado esperado (para el indicador predeterminado PREG_PATTERN_ORDER). La primera entrada de $newStr contiene todas las coincidencias de patrones completos, el siguiente resultado todas las coincidencias para el primer subpatrón (entre paréntesis) y así sucesivamente.

+0

ah, tiene sentido ahora ... gracias por la respuesta – Brodie

1

La primera matriz en el resultado de preg_match_all devuelve las cadenas que coinciden con el patrón completo que pasó a la función preg_match_all(), en su caso/\^([^^] *?) \ ~ /. Las matrices posteriores en el resultado contienen las coincidencias para los paréntesis en su patrón.Tal vez sea más fácil de entender con un ejemplo:

$string = 'abcdefg'; 
preg_match_all('/ab(cd)e(fg)/', $string, $matches); 

El $ coincide con arreglo será

array(3) { 
    [0]=> 
    array(1) { 
    [0]=> 
    string(7) "abcdefg" 
    } 
    [1]=> 
    array(1) { 
    [0]=> 
    string(2) "cd" 
    } 
    [2]=> 
    array(1) { 
    [0]=> 
    string(2) "fg" 
    } 
} 

La primera matriz contendrá el partido de todo el patrón, en este caso 'ABCDEFG'. La segunda matriz contendrá la coincidencia para el primer conjunto de paréntesis, en este caso 'cd'. La tercera matriz contendrá la coincidencia para el segundo conjunto de paréntesis, en este caso 'fg'.

2

¿Podría este RegEx se ha estructurado de tal manera que omitir la primera entrada de la matriz y solo producir el resultado deseado?

Absolutamente. Use assertions. Esta expresión regular:

preg_match_all('/(?<=\^)[^^]*?(?=~)/', $str, $newStr); 

Resultados en:

Array 
(
    [0] => Array 
     (
      [0] => Jony 
      [1] => Smith 
      [2] => [email protected] 
     ) 

) 
0

Siempre que tenga problemas de imaginar la función de preg_match_all se debe utilizar un evaluador como preg_match_all tester @ regextester.net

Esto le muestra el resultado en tiempo real y se puede configurar cosas como el orden de los resultados, meta instrucciones, captura de compensación y muchos más.

Cuestiones relacionadas