2010-02-05 20 views
8

tengo una cadena que puede ser algo como esto:PHP de expresiones regulares - Repetición del partido de un grupo

$r = 'Filed under: <a>Group1</a>, <a>Group2</a>'; 

Aquí es la expresión regular que estoy usando hasta ahora:

preg_match_all("/Filed under: (?:<a.*?>([\w|\d|\s]+?)<\/a>)+?/", $r, $matches); 

quiero la expresión regular dentro del () para continuar haciendo coincidencias como se designa con el +? al final. Pero simplemente no lo hará. :: suspiro ::

Cualquier idea. Sé que tiene que haber una manera de hacer esto en una expresión regular en lugar de dividirla.

Respuesta

5

Probar:

<?php 

$r = 'Filed under: <a>Group1</a>, <a>Group2</a>, <a>Group3</a>, <a>Group4</a>'; 

if(preg_match_all("/<a.*?>([^<]*?)<\/a>/", $r, $matches)) { 
    var_dump($matches[1]); 
} 

?> 

de salida:

array(4) { 
    [0]=> 
    string(6) "Group1" 
    [1]=> 
    string(6) "Group2" 
    [2]=> 
    string(6) "Group3" 
    [3]=> 
    string(6) "Group4" 
} 

EDIT:

Desde desea incluir la cadena 'Archivado bajo' en la búsqueda para identificar de forma exclusiva el partido, se puede probar esto, no estoy seguro de si se puede hacer usando una sola llamada a preg_match

// Since you want to match everything after 'Filed under' 
if(preg_match("/Filed under:(.*)$/", $r, $matches)) { 
    if(preg_match_all("/<a.*?>([^<]*?)<\/a>/", $matches[1], $matches)) { 
     var_dump($matches[1]); 
    } 
} 
+0

Gracias, pero realmente necesito usar el indicador "Archivado en:". Si bien mi texto de ejemplo era rudimentario, el archivo real que estoy analizando es bastante complicado, y archivado en: es realmente el único identificador único con el que tengo que trabajar. Afortunadamente, está al final del archivo, por lo que puedo hacer coincidir todo el camino hasta el final. –

+0

Lo suficientemente cerca. :) Gracias. –

1

Quiero la expresión regular dentro del() para continuar haciendo coincidencias como se designa con el +? al final.

+? es un cuantificador perezoso - que coincidirá con el menor número de veces como sea posible. En otras palabras, solo una vez.

Si quiere hacer coincidir varias veces, quiere un cuantificador codicioso - +.

También tenga en cuenta que su expresión regular no funciona: la coincidencia falla tan pronto como encuentra la coma entre las etiquetas, porque no la ha contabilizado. Eso probablemente necesita corrección.

+0

Correcto, lo he intentado solo con el + cuantificador. Eso también falla. Y también pensé en la, [coma] a la que me temo que no sé cómo configurar esto, ya que el segundo o tercer partido puede tener o no una coma. Sin embargo, intenté esto como mi intento: [código] preg_match_all ("/ Archivado en: (?: ([\ w | \ | | s] +?) <\/a>. *?) + /", $ R , $ coincidencias); [/ code] –

+0

Hmmm, los comentarios no se ven muy bonitos. –

+0

@Senica: puede usar los trazos para formatear el código en los comentarios, al igual que en las preguntas y respuestas, pero si el código es largo o complejo, debe editar la pregunta y colocarla en su lugar. El código que incluiste anteriormente era demasiado para un comentario. –

2
$r = 'Filed under: <a>Group1</a>, <a>Group2</a>' 
$s = explode("</a>",$r); 
foreach ($s as $k){ 
    if ($k){ 
     $k=explode("<a>",$k); 
     print "$k[1]\n"; 
    } 
} 

salida

$ php test.php 
Group1 
Group2 
+1

A veces, RegExes realmente es la mejor manera de hacer algo ... – SoapBox

+1

mejor o no, depende de cada individuo. Si se puede hacer sin expresiones regulares complicadas, entonces para mí es lo mejor, tanto para mí como para quien lo mantiene. – ghostdog74

+0

Como expliqué en un comentario anterior, no puedo usar la explosión .... Para empezar, hay casos en los que no hay coma y solo hay un Grupo. Dos, aunque mi ejemplo fue simple, este es un archivo complicado. La etiqueta tampoco es tan simple. Tres, necesito el atributo Archivado en: dado que usar una explosión seguramente devolverá valores no deseados. –

8

Sólo por diversión aquí es una expresión regular que trabajará con un único preg_match_all:

'%(?:Filed under:\s*+|\G</a>)[^<>]*+<a[^<>]*+>\K[^<>]*%` 

O, en un formato más legible:

'%(?: 
     Filed under: # your sentinel string 
    |     
     \G    # NEXT MATCH POSITION 
     </a>   # an end tag 
) 
    [^<>]*+   # some non-tag stuff  
    <a[^<>]*+>  # an opening tag 
    \K    # RESET MATCH START 
    [^<>]+   # the tag's contents 
%x' 

\G coincide con la posición donde comenzaría el siguiente intento de coincidencia, que suele ser el lugar donde finalizó la partida anterior exitosa (pero si la partida anterior fue de longitud cero, se adelanta una más). Eso significa que la expresión regular no coincidirá con una subcadena que comience por </a> hasta después de, que coincide con una que comienza con Filed under: al menos una vez.

Después de que la cadena de centinela o una etiqueta final se haya emparejado, [^<>]*+<a[^<>]*+> consume todo, incluso la siguiente etiqueta de inicio. A continuación, \K falsifica la posición de inicio, por lo que parece que se inicia la coincidencia (si hay una) después de la etiqueta <a> (es como un aspecto positivo pero más flexible). Finalmente, [^<>]+ coincide con el contenido de la etiqueta y lleva la posición del partido hasta la etiqueta final para que \G pueda coincidir.

Pero, como dije, esto es solo por diversión. Si no tiene tiene para hacer el trabajo en una expresión regular, es mejor con un enfoque de varios pasos como el que usa @codaddict; es más legible, más flexible y más fácil de mantener.

\K reference
\G reference

EDIT: Aunque las referencias que he dado son para la documentación de Perl, estas características son apoyado por PHP, también - o, más exactamente, por la lib PCRE. Creo que los documentos de Perl son un poco mejores, pero también puedes leer sobre esto en el PCRE manual.

+0

No sabía sobre '\ K'. ¡Interesante! Una pequeña nota sobre '\ G' - se refiere a la" coincidencia previa ", que está bien, y al" próximo partido ", lo cual es un poco confuso (Especialmente cuando el ejemplo de Perl al que se ha vinculado es francamente engañoso - * establece * la siguiente posición en el código - ** que es muy diferente del comportamiento predeterminado **). Simplemente ponga - '\ G' se refiere a la posición en la que se intentó iniciar la coincidencia actual. Tampoco es exacto' 'siempre coincidirá después de' Archivado en: '- también puede coincidir al comienzo de la cadena, para ejemplo ', Group2': http://ideone.com/aTjrm. – Kobi

+0

(por cierto, vengo de aquí: http://stackoverflow.com/questions/5982451/regex-capturing-a-repeated-group/7135730#7135730) – Kobi

+0

Hmm, en realidad, mi definición de '\ G' es tampoco es bueno. – Kobi

Cuestiones relacionadas