2013-02-15 11 views
5

Ho difficoltà a comprendere come l'ancoraggio \G funzioni nel gusto PHP delle espressioni regolari.Qual è l'uso dell'ancora ' G' in regex?

Sono incline a pensare (anche se potrei sbagliarmi) che \G viene utilizzato al posto di ^ in situazioni in cui si verificano più corrispondenze della stessa stringa.

Qualcuno potrebbe mostrare un esempio di come utilizzare \G e spiegare come e perché funziona?

+0

Dai un'occhiata a questa risposta per un esempio reale: http://stackoverflow.com/a/2248130/1606729 – koopajah

+0

@koopajah - grazie. Sfortunatamente, non è un esempio corretto. Sto chiedendo di usare l'anchor di \ G; l'esempio a cui sei collegato usa \ g come riferimento. –

+0

Grazie ancora, @koopajah. Il nuovo esempio utilizza effettivamente \ G, ma da quell'esempio non riesco ancora a capire nulla su come e perché dovrebbe essere usato \ G. L'unica cosa che vedo è che qui viene usato \ G, ma perché è usato, in quali altre situazioni dovrebbe essere usato, e così via - non lo capisco. Altri esempi, per favore? –

risposta

3

UPDATE

\ G costringe il modello per restituire solo le partite che fanno parte di una catena continua di abbinamento. Dalla prima partita ogni partita successiva deve essere preceduta da una corrispondenza. Se rompi la catena, le partite finiscono.

<?php 
$pattern = '#(match),#'; 
$subject = "match,match,match,match,not-match,match"; 

preg_match_all($pattern, $subject, $matches); 

//Will output match 5 times because it skips over not-match 
foreach ($matches[1] as $match) { 
    echo $match . '<br />'; 
} 

echo '<br />'; 

$pattern = '#(\Gmatch),#'; 
$subject = "match,match,match,match,not-match,match"; 

preg_match_all($pattern, $subject, $matches); 

//Will only output match 4 times because at not-match the chain is broken 
foreach ($matches[1] as $match) { 
    echo $match . '<br />'; 
} 
?> 

Questo è direttamente dalla documentazione

La quarta utilizzo di backslash è per certe affermazioni semplici. Un'asserzione specifica una condizione che deve essere soddisfatta in un particolare punto in una corrispondenza, senza consumare alcun carattere dalla stringa dell'oggetto. L'uso di sottoprogrammi per asserzioni più complesse è descritto di seguito. Le affermazioni backslash sono

\G 
    first matching position in subject 

La \ G affermazione è vera solo quando la posizione di corrispondenza corrente è il punto di inizio della partita, come specificato dall'argomento offset preg_match(). Differisce da \ A quando il valore dell'offset è diverso da zero.

http://www.php.net/manual/en/regexp.reference.escape.php

Si dovrà scorrere verso il basso la pagina un po ', ma è così.

C'è un esempio molto buono in ruby ​​ma è lo stesso in PHP.

How the Anchor \z and \G works in Ruby?

+0

Grazie @Jrod, è un passo nella giusta direzione per me, e apprezzo il tuo posting link ai documenti. Sfortunatamente, essendo relativamente nuovo a PHP e alla programmazione in generale, non intendo assolutamente il significato pratico e concreto di quella cosa dai documenti. Ecco perché sto chiedendo un esempio. –

+0

@DimitriVorontzov Ho aggiunto un semplice esempio. Spero che lo renda più chiaro. – Jrod

+0

Questo è fantastico, grazie mille @Jrod! –

4

\G corrisponderà il confine partita, che è sia l'inizio della stringa, o il punto in cui si consuma l'ultimo carattere della scorsa partita.

È particolarmente utile quando è necessario eseguire tokenizzazione complessa, assicurandosi inoltre che i token siano validi.

problema Esempio

Prendiamo l'esempio di creazione di token questo ingresso:

input 'some input in quote' more input '\'escaped quote\'' [email protected]_$of_fun ' \' \\ ' crazy'stuff' 

In questi token (io uso ~ per indicare fine della stringa):

input~ 
some input in quote~ 
more~ 
input~ 
'escaped quote'~ 
[email protected]_$of_fun~ 
' \ ~ 
crazy~ 
stuff~ 

La stringa è composta da un mix di:

  • Stringa citata singolarmente, che consente la fuga di \ e ' e gli spazi sono conservati. La stringa vuota può essere specificata usando una stringa citata singolarmente.
  • O una stringa non quotata, che consiste in una sequenza di caratteri non di spazio bianco e non contiene \ o '.
  • Lo spazio tra 2 stringa non quotata li delimiterà. Lo spazio non è necessario per delimitare altri casi.

Per semplicità, assumiamo l'ingresso non contiene nuova linea (nel caso reale, si necessità a considerarlo). Aggiungerà alla complessità della regex senza dimostrare il punto.

La regex RAW per la stringa singolarmente citato è '(?:[^\\']|\\[\\'])*+'
E l'espressione regolare RAW per stringa non quotate è [^\s'\\]++
Non è necessario prendersi cura troppo del 2 pezzo di regex sopra, però.

La soluzione qui di seguito con \G può fare in modo che quando il motore non riesce a trovare alcuna corrispondenza, tutti caratteri dall'inizio della stringa in posizione di ultimo match è stato consumato. Dal momento che non può saltare il personaggio, il motore smetterà di combaciare quando non riesce a trovare una corrispondenza valida per entrambe le specifiche dei token, piuttosto che afferrare cose a caso nel resto della stringa.

Edilizia

Al primo passo di costruzione, siamo in grado di mettere insieme questo regex:

\G(?:'((?:[^\\']|\\[\\'])*+)'|([^\s'\\]++)) 

O semplicemente mettere (questo è non regex - solo per fare più facile da leggere):

\G(Singly_quote_regex|Unquoted_regex) 

Questo corrisponderà solo al primo token, poiché quando si tenta corrispondenze pts per la seconda volta, la partita si ferma nello spazio prima dello 'some input....


Abbiamo solo bisogno di aggiungere un po 'per consentire 0 o più spazio, in modo che nella successiva partita, lo spazio nella posizione lasciata fuori dalla ultima partita si consuma:

\G *+(?:'((?:[^\\']|\\[\\'])*+)'|([^\s'\\]++)) 

L'espressione regolare di cui sopra ora identifica correttamente i token, come visto here.


La regex può essere ulteriormente modificata in modo che restituisce il resto della stringa quando il motore non riesce a recuperare qualsiasi gettone valido:

\G *+(?:'((?:[^\\']|\\[\\'])*+)'|([^\s'\\]++)|((?s).+$)) 

Poiché l'alternanza è provato in ordine da sinistra a -right, l'ultima alternativa ((?s).+$) corrisponderà se e solo se la stringa avanti non costituisce un token quotato singolo o non quotato valido. Questo può essere usato per controllare l'errore.

Il primo gruppo di cattura conterrà il testo all'interno di singola stringa citato, che esigenze di elaborazione in più di trasformarsi nel testo desiderato (in realtà non è rilevante qui, quindi lo lascio come esercizio per il lettore). Il secondo gruppo di acquisizione conterrà la stringa non quotata. E il terzo gruppo di cattura agisce come un indicatore che la stringa di input non è valida.

Demo for the final regex

Conclusione

L'esempio precedente è dimostrare di uno scenario di utilizzo di \G in tokenizzazione. Ci possono essere altri usi che non ho incontrato.

+0

grazie! L'esempio è decisamente sofisticato, lascia che lo analizzi. –

+1

@DimitriVorontzov: Questo è più di un utilizzo del caso quasi reale, quindi è piuttosto complesso. – nhahtdh

+0

Sì, lo apprezzo, @nhahtdh! –