2010-02-05 19 views
8

ho una stringa che potrebbe essere simile a questa:PHP espressioni regolari - Ripetizione partita di un gruppo

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

Ecco l'espressione regolare sto utilizzando finora:

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

voglio l'espressione regolare all'interno dello () continua a creare corrispondenze come indicato con lo +? alla fine. Ma semplicemente non lo farà. :: sospiro ::

Tutte le idee. So che ci deve essere un modo per farlo in una espressione regolare invece di rompere.

risposta

5

Prova:

<?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]); 
} 

?> 

uscita:

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

EDIT:

Dal momento che si desidera includere la stringa 'Filed under' nella ricerca per identificare in modo univoco la partita, si può provare questo, non sono sicuro se può essere fatto utilizzando una singola chiamata a funzione 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

Grazie, ma ho davvero bisogno di usare il flag "Filed under:". Mentre il mio testo di esempio era rudimentale, il file che sto analizzando è piuttosto complicato e Archiviato in: è davvero l'unico identificatore univoco con cui devo lavorare. Fortunatamente, è alla fine del file, quindi posso abbinare fino in fondo. –

+0

Abbastanza vicino. :) Grazie. –

1

Voglio che l'espressione regolare all'interno di() continui a creare corrispondenze come indicato con +? alla fine.

+? è un quantificatore pigro - è abbinerà il minor numero di volte possibile. In altre parole, solo una volta.

Se si desidera far corrispondere più volte, si desidera un quantificatore avido - +.

Si noti inoltre che la vostra espressione regolare non funziona del tutto - la partita non appena incontra la virgola tra i tag, perché non hai rappresentato per esso. Questo probabilmente ha bisogno di essere corretto.

+0

Sì, ho provato solo con il quantificatore +. Anche questo fallisce. E ho anche pensato alla, [virgola] a cui temo di non sapere come impostare questo, dal momento che la seconda o la terza partita può avere o meno una virgola. Tuttavia, ho provato questo come mio tentativo: [codice] preg_match_all ("/ Archiviato in: (?: ([\ w | \ d | \ s] +?) <\/a>. *?) + /", $ R , $ partite); [/ code] –

+0

Hmmm, i commenti non sembrano molto belli. –

+0

@Senica: è possibile utilizzare i backtick per formattare il codice nei commenti proprio come è possibile nelle domande e nelle risposte, ma se il codice è lungo o complesso, è necessario modificare la domanda e inserirla al suo posto. Il codice che hai incluso sopra era un po 'troppo per un commento. –

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"; 
    } 
} 

uscita

$ php test.php 
Group1 
Group2 
+1

A volte le RegEx sono davvero il modo migliore per fare qualcosa .... – SoapBox

+1

meglio o no, dipende dal singolo. Se può essere fatto senza regex complicate, allora per me è il meglio, sia per me che per chi lo mantiene. – ghostdog74

+0

Come ho spiegato in un commento sopra, non posso usare explode .... Per uno, ci sono casi in cui non esiste una virgola e c'è un solo gruppo. Due, mentre il mio esempio era semplice, questo è un file complicato. Il tag non è neanche così semplice. Tre, ho bisogno del Filed under: l'attributo come usando un explode restituirebbe sicuramente valori indesiderati. –

8

solo per divertimento ecco un'espressione regolare che funzionerà con una sola preg_match_all:

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

Oppure, in un formato più leggibile:

'%(?: 
     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 corrisponde alla posizione in cui inizia il successivo tentativo di corrispondenza, che di solito è il punto in cui è terminata la precedente partita andata a buon fine (ma se la precedente corrispondenza era a lunghezza zero, salta in avanti un'altra). Ciò significa che l'espressione regolare non corrisponderà una sottostringa partendo </a> fino dopo è abbinato uno a partire con Filed under: in almeno una volta.

Dopo che la stringa sentinella o un tag di chiusura sono stati abbinati, [^<>]*+<a[^<>]*+> consuma tutto fino al tag di inizio successivo incluso. Quindi \K esegue lo spoofing della posizione iniziale in modo che la corrispondenza (se presente) venga avviata dopo il tag <a> (è come un lookbehind positivo, ma più flessibile). Infine, [^<>]+ corrisponde al contenuto del tag e porta la posizione della corrispondenza fino al tag di fine, in modo che \G possa corrispondere.

Ma, come ho detto, questo è solo per divertimento. Se non lo fai avere per fare il lavoro in una regex, stai meglio con un approccio multi-passo come quello usato da @codaddict; è più leggibile, più flessibile e più gestibile.

\K reference
\G reference

EDIT: Anche se i riferimenti che ho dato sono per la documentazione Perl, queste caratteristiche sono supportata da PHP, anche - o, più precisamente, dal lib PCRE. Penso che i documenti Perl siano un po 'migliori, ma puoi anche leggere su questo materiale nello PCRE manual.

+0

Non sapevo di '\ K'. Interessante! Una piccola nota su '\ G' - ti riferisci alla" partita precedente ", che è OK, e alla" prossima partita ", che è un po 'confusa (Specialmente quando l'esempio Perl a cui ti sei collegato è decisamente fuorviante - * imposta * la prossima posizione nel codice - ** che è molto diversa dal comportamento predefinito **). In poche parole - '\ G' si riferisce alla posizione in cui si è tentato di iniziare la corrispondenza corrente. Inoltre,' 'corrisponderà sempre dopo' Archiviato in: '- può anche corrispondere all'inizio della stringa, per esempio ', Gruppo2': http://ideone.com/aTjrm. – Kobi

+0

(a proposito, sono venuto da qui: http://stackoverflow.com/questions/5982451/regex-capturing-a-repeated-group/7135730#7135730) – Kobi

+0

Hmm, in realtà, la mia definizione di '\ G' è non va bene neanche – Kobi

Problemi correlati