2011-10-19 7 views
5

Sto ancora imparando molto su PHP e l'alterazione delle stringhe è qualcosa che mi interessa. Ho usato preg_match prima per cose come la convalida di un indirizzo email o semplicemente la ricerca di richieste.Come preg_match_all() elabora le stringhe?

Sono appena arrivato da questo post What's wrong in my regular expression? ed ero curioso di sapere perché la funzione preg_match_all produce 2 stringhe, 1 w/alcuni dei caratteri eliminati e quindi l'altro con l'output desiderato.

Da quello che ho capito della funzione è che va oltre la stringa carattere per carattere utilizzando il RegEx per valutare cosa fare con esso. Questo RegEx potrebbe essere stato strutturato in modo da bypassare la prima voce dell'array e solo produrre il risultato desiderato?

e così non c'è bisogno di andare in altro thread

$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>'; 
} 

Questa volontà di uscita

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


Jony
Smith
[email protected]

Sono curioso di sapere se il motivo per 2 voci di array è dovuto alla sytax originale della stringa o se è la normale risposta di elaborazione della funzione. Scusa se questo non dovrebbe essere qui, ma sono davvero curioso di sapere come funziona.

grazie, Brodie

+0

L'output conterrà sempre l'intera corrispondenza e una voce per ciascun gruppo di cattura nell'espressione. –

+0

Non una risposta, ma interessante notare qui è il flag 'PREG_SET_ORDER', che restituirà un elenco di risultati più semplice. E mentre non è possibile rimuovere la voce dell'array '[0]' per la corrispondenza completa, è possibile eliminarne il contenuto usando '\ K' nella regex. – mario

risposta

2

E 'un comportamento standard per preg_match e preg_match_all - la prima stringa nella matrice "valori abbinati" è la stringa FULL che è stata catturata dal pattern regex. I successivi valori dell'array sono i "gruppi di cattura", la cui esistenza dipende dal posizionamento/posizione delle coppie () nel modello regex.

Nel caso del vostro regex, /\^([^^]*?)\~/, la stringa completa corrispondenza sarebbe

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

Ah capisco, quindi la prima cosa che fa è trovare il testo che inizia con w/^ e termina con ~ e poi la seconda espressione in() prende tutto dopo^meno il ~. Immagino che la curiosità abbia il meglio di me, se [^^] *? dice di afferrare il testo dopo "^" perché allora non afferra il '~'? – Brodie

+0

Lo fa, ma il '~' non è all'interno del tuo gruppo di cattura, quindi verrà visualizzato solo nella sezione '[0]'. Puoi considerare l'intero modello regex come un gruppo di cattura stesso, in modo tale che l'acquisizione virtuale sia memorizzata in '[0]', e quindi qualsiasi cattura che crei esplicitamente con '()' vai in [1], [2], ecc ... –

+0

'[^^] *?' si traduce in 'tanti caratteri (*, '0 o più') che NON sono a^([^^]), in modo non avido (?). –

0

[0] contiene tutto il match, mentre [1] solo una parte (la parte che si desidera estrarre) ... Si può fare var_dump($newStr) per vedere la struttura a matrice, potrai capirlo .

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

Questo si tradurrà (espressione risultato strano, non si sono modificati) in ...

Jony 
Smith 
example- 
     [email protected] 
1

quanto manual stati, questo è il risultato atteso (per il flag di default PREG_PATTERN_ORDER). La prima voce di $newStr contiene tutte le corrispondenze di modello completo, il risultato successivo tutte le corrispondenze per la prima subpattern (tra parentesi) e così via.

+0

ah ha senso ora ... grazie per la risposta – Brodie

1

Il primo array nel risultato di preg_match_all restituisce le stringhe che corrispondono all'intero pattern passato alla funzione preg_match_all(), nel tuo caso/\^([^^] *?) \ ~ /. Gli array successivi nel risultato contengono le corrispondenze per le parentesi nel modello.Forse è più facile da capire con un esempio:

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

Il $ corrisponde gamma sarà

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

Il primo array conterrà la partita di tutto il modello, in questo caso 'abcdefg'. Il secondo array conterrà la corrispondenza per il primo set di parentesi, in questo caso 'cd'. Il terzo array conterrà la corrispondenza per il secondo gruppo di parentesi, in questo caso 'fg'.

2

Questo RegEx potrebbe essere stato strutturato in modo tale da ignorare la prima immissione di array e solo produrre il risultato desiderato?

Assolutamente. Utilizzare assertions. Questa espressione regolare:

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

risultati in:

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

) 
0

Ogni volta che avete problemi di immaginare la funzione di preg_match_all si dovrebbe usare un valutatore come preg_match_all tester @ regextester.net

Questo mostra il risultato in tempo reale e si può configurare cose come l'ordine dei risultati, le meta istruzioni, l'acquisizione offset e molti altri.