2010-01-27 25 views
7

Durante il test di una risposta per another user's question ho trovato qualcosa che non capisco. Il problema era di sostituire tutti i letterali \t\n\r caratteri da una stringa con un singolo spazio.Extra barra rovesciata necessaria nel modello regexp di PHP

Ora, il primo modello che ho provato era:

/(?:\\[trn])+/ 

che sorprendentemente non ha funzionato. Ho provato lo stesso modello in Perl e ha funzionato bene. Dopo alcuni tentativi ed errori ho scoperto che PHP vuole 3 o 4 barre rovesciate per quel modello da abbinare, come in:

/(?:\\\\[trn])+/ 

o

/(?:\\\[trn])+/ 

questi modelli - con mia grande sorpresa - sia il lavoro. Perché sono necessari questi backslash aggiuntivi?

+1

Perl espressioni regolari sono integrate nel linguaggio, quindi è necessario solo due barre inverse. –

risposta

12

avete bisogno di 4 backslash per rappresentare 1 in regex perché:

  • 2 backslash sono utilizzati per unescaping in una stringa ("\\\\" -> \\)
  • 1 barra rovesciata viene utilizzato per unescaping nel motore regex (\\ -> \)

Dal documento PHP,

fuga qualsiasi altro carattere comporterà la barra rovesciata in fase di stampa troppo 1

Quindi per \\\[,

  • 1 barra rovesciata viene utilizzata per unescaping la \, un soggiorno perché \[ è valido ("\\\[" -> \\[)
  • 1 barra inversa per il rimando in sequenza nel motore regex (\\[ -> \[)

Sì, funziona, ma non è una buona pratica.

2

L'espressione regolare è solo /(?:\\[trn])+/. Ma dal momento che è necessario per sfuggire alle backslash nelle dichiarazioni di stringa così, ogni backslash deve essere espresso con \\:

"/(?:\\\\[trn])+/" 
'/(?:\\\\[trn])+/' 

soli tre backspace, inoltre, funzionano perché PHP non conosce la sequenza di escape \[ e lo ignora. Quindi \\ diventerà \ ma \[ rimarrà \[.

+0

Allora perché funzionano 3 backslash? E perché in questo caso le virgolette singole non sono diverse dalle virgolette doppie? –

+0

@kemp: aggiornata la mia risposta. – Gumbo

+0

Gumbo :: solo così so se ho capito bene - questo caso funziona perché '\ [' non è un carattere di controllo ** e ** non diventa una parentesi quadra aperta letterale perché il modello è analizzato da sinistra a destra quindi il backslash viene collegato a quello precedente e precedentemente sfuggito? –

8

sue opere in Perl, perché si passa che direttamente come schema di espressione regolare /(?:\\[trn])+/

ma in PHP, è necessario passare come stringa, quindi hanno bisogno di più sfuggire per backslash stesso.

"/(?:\\\\[trn])+/" 

La regex \ per indicare un singolo backslash sarebbe diventato '/ \\\\ /' come PHP preg string

-2

Usa str_replace!

$code = str_replace(array("\t","\n","\r"),'',$code); 

dovrebbe fare il trucco

+1

Questo non risponde alla mia domanda, ed è anche sbagliato perché str_replace() non consente la sostituzione di tutti i caratteri richiesti (comunque molti lo sono) con una sola citazione - puoi semplicemente rimuoverli tutti. –

+0

@ kemp si lo fa. Se non rimuove le combinazioni di \ r \ n o \ n \ r – AntonioCS

+1

No, non puoi sostituire, ad esempio, tre (o qualsiasi numero arbitrario) di quelli con un singolo spazio bianco, a meno che tu non voglia fornire ** ogni ** combinazione possibile. Quello che fa il tuo codice è solo rimuoverli tutti. –

Problemi correlati