2015-05-25 26 views
5

Sto provando a scrivere un'espressione regolare per dividere una stringa in elementi separati all'interno di parentesi graffe corrispondenti. Prima di tutto, deve essere ricorsivo, e in secondo luogo, deve restituire gli offset (come con PREG_OFFSET_CAPTURE).Scrittura di un'espressione per estrarre ricorsivamente i dati tra parentesi

In realtà penso che questo sia probabilmente un modo meno efficiente per elaborare questi dati, ma non sono sicuro di una tecnica più semplice e più orientata alle prestazioni. (Se hai uno, mi piacerebbe sentirlo!)

Quindi, l'ingresso può essere in questo formato:

Hello {#name}! I'm a {%string|sentence|bit of {#random} text} 

L'elaborazione dei dati è abbastanza facile se è in questo formato :

Hello {#name}! I'm a {%string|sentence|bit of random text} 

Ma sono le parentesi graffe ricorsive all'interno di un altro insieme di parentesi graffe che è il problema quando si tratta di elaborazione. Sto utilizzando il seguente codice per dividere la stringa:

preg_match_all("/(?<={)[^}]*(?=})/m", $string, $braces, PREG_OFFSET_CAPTURE); 

E come prima accennato, è molto bello per il semplice modulo. Poco meno per la forma più complicata. L'intenzione per questo (e l'ho funzionale in una forma non ricorsiva) è di sostituire ogni area parentesi con il contenuto come elaborato dalle funzioni, lavorando verso l'alto.

Idealmente, mi piacerebbe essere in grado di scrivere Hello {#name}! I'm a {%string|sentence|bit of {?(random == "strange") ? {#random} : "strange"}} text} e per essere gestibile.

Qualsiasi aiuto sarebbe molto apprezzato.

+0

Così, per 'Ciao {} # nome! Sono un {% string | frase | bit di {#random} text} ', è necessario acquisire' {#name} ',' {% string | frase | bit di {#random} text} ', e' {} #random '? –

+0

Esattamente. E ho anche bisogno di catturare idealmente le posizioni! Anche se penso ancora che ci debba essere un modo migliore per farlo, questo richiede un po 'di tempo in stringhe molto lunghe. – Forest

+0

Se il tuo obiettivo è sostituire ogni parentesi, l'utilizzo di un pattern ricorsivo non sarà utile. Quello di cui hai bisogno è di sostituire la parentesi più interna finché non ci sono più parentesi nella tua stringa. –

risposta

2

È possibile sfruttare la potenza reex di PCRE per l'acquisizione di gruppi in look-ahead e subroutine per ottenere le sottostringhe nidificate {...}.

A regex demo is available here.

$re = "#(?=(\{(?>[^{}]|(?1))*+\}))#"; 
$str = "Hello {#name}! I'm a {%string|sentence|bit of {#random} text}"; 
preg_match_all($re, $str, $matches, PREG_OFFSET_CAPTURE); 
print_r($matches[1]); 

Vedi IDEONE demo

Si restituisce un array con il catturato {...} - come le corde e le loro posizioni:

Array 
(
    [0] => Array 
     (
      [0] => {#name} 
      [1] => 6 
     ) 

    [1] => Array 
     (
      [0] => {%string|sentence|bit of {#random} text} 
      [1] => 21 
     ) 

    [2] => Array 
     (
      [0] => {#random} 
      [1] => 46 
     ) 

) 
+0

Questo risolve il mio problema. C'è un metodo che sarebbe supportato anche con JavaScript, forse? Sto lavorando su questo con PHP, ma voglio portarlo a un certo punto su JavaScript. – Forest

+0

In JavaScript, non esiste alcun supporto per le subroutine nella regex.Ciò significa che non potrai abbinare le parentesi graffe annidate con espressioni regolari. –

+0

Suppongo che la mia unica opzione per quello sarà una forma di parser/lexer o qualcosa del genere? – Forest

Problemi correlati