2009-03-29 4 views
13

Sto tentando di trovare una stringa che può apparire su più righe. Si inizia e finisce con una stringa specifica:Inclusione di nuove righe nella funzione preg_replace di PHP

{a}some string 
can be multiple lines 
{/a} 

Posso prendere tutto tra {a} e {/a} con una regex? Sembra il. non corrisponde alle nuove righe, ma ho provato quanto segue senza fortuna:

$template = preg_replace($'/\{a\}([.\n]+)\{\/a\}/', 'X', $template, -1, $count); 
echo $count; // prints 0 

Corrisponde. o \ n quando sono da soli, ma non insieme!

risposta

31

Utilizzare la s modifier:

$template = preg_replace($'/\{a\}([.\n]+)\{\/a\}/s', 'X', $template, -1, $count); 
//            ^
echo $count; 
+0

Fantastico, sapevo che sarebbe stato qualcosa di semplice! – DisgruntledGoat

+0

Inoltre, ho appena scoperto che questa informazione è sul sito Web di PHP, anche se non l'ho mai trovata prima quando guardo ... http://www.php.net/manual/en/reference.pcre.pattern.modifiers .php – DisgruntledGoat

3

Da http://www.regular-expressions.info/dot.html:

"Il punto corrisponde a un singolo carattere, senza preoccuparsi di ciò che quel personaggio è L'unica eccezione sono di nuova riga personaggi".

sarà necessario aggiungere un contrassegno trailing/s all'espressione.

6

Penso che tu abbia più problemi del solo punto che non corrisponde a newline, ma lasciami iniziare con una raccomandazione di formattazione. Puoi usare praticamente qualsiasi carattere di punteggiatura come il delimitatore regex, non solo la barra ('/'). Se usi un altro personaggio, non dovrai sfuggire alle barre all'interno della regex. Capisco che "%" è popolare tra i PHP; che renderebbe il vostro argomento modello:

'%\{a\}([.\n]+)\{/a\}%' 

Ora, la ragione per cui espressione regolare non ha funzionato come desiderato è perché il punto perde il suo significato speciale quando appare all'interno di una classe di caratteri (le parentesi quadre) - così [.\n] corrisponde solo a un punto o a un avanzamento di riga. Che cosa stavate cercando era (?:.|\n), ma avrei consigliato corrispondente al ritorno a capo così come il ritorno a capo:

'%\{a\}((?:.|[\r\n])+)\{/a\}%' 

Ecco perché la parola "ritorno a capo" può riferirsi alla stile Unix "\ n", Stile "\ r \ n" in stile Windows o "Mac" stile "vecchio". Qualsiasi pagina Web può contenere una di queste o una combinazione di due o più stili; un mix di "\ n" e "\ r \ n" è molto comune. Ma con la modalità/s (nota anche come modalità DOTALL a linea singola o), non è necessario preoccuparsi di questo:

'%\{a\}(.+)\{/a\}%s' 

Tuttavia, c'è un altro problema con il regex originale che è ancora presente in questo: il + è goloso. Ciò significa che se nel testo è presente più di una sequenza {a}...{/a}, la prima volta che viene applicata la tua espressione regolare corrisponderà a tutte, dal primo {a} all'ultimo {/a}. Il modo più semplice per risolvere il problema che è quello di rendere il + ungreedy (aka, "pigro" o "riluttante"), aggiungendo un punto interrogativo:

'%\{a\}(.+?)\{/a\}%s' 

Infine, non so cosa fare della '$ 'prima della citazione di apertura del tuo argomento pattern. Non faccio PHP, ma mi sembra un errore di sintassi. Se qualcuno potesse educarmi in questa faccenda, lo apprezzerei.

+0

Oh, che deve essere un errore di battitura - stavo usando una variabile in origine e l'ho sostituita con una stringa per questo esempio. – DisgruntledGoat

+0

Questa è stata una grande spiegazione. Saluti per questo. – craignewkirk