Differenza tra \ A \ z e ^ $ nelle espressioni regolari di Ruby


196

Nella documentazione ho letto:

Usa \ A e \ z per abbinare l'inizio e la fine della stringa, ^ e $ corrispondono all'inizio / fine di una riga.

Ho intenzione di applicare un'espressione regolare per verificare il nome utente (o l'e-mail è la stessa) inviato dall'utente. Con quale espressione dovrei usare validates_format_ofnel modello? Non riesco a capire la differenza: ho sempre usato ^ e $ ...


Risposte:


226

Se si dipende dall'espressione regolare per la convalida, si desidera sempre utilizzare \Ae \z. ^e $si abbineranno solo fino a un carattere di nuova riga, il che significa che potrebbero usare un messaggio di posta elettronica me@example.com\n<script>dangerous_stuff();</script>e farlo convalidare, poiché la regex vede solo tutto prima di \n.

La mia raccomandazione sarebbe solo di rimuovere completamente le nuove righe da un nome utente o e-mail in anticipo, dal momento che non c'è praticamente alcun motivo legittimo per uno. Quindi puoi tranquillamente usare EITHER \A \zo ^ $.


13
@Ragmaanir ha ragione, dovrebbe essere con una piccola lettera \zanziché \Z!
Petr

11
+1 Grazie! Anche se dovrei essere in disaccordo con la tua raccomandazione: A) Non aggiungere lavori / elaborazioni inutili se c'è un'opportuna soluzione, e B) soprattutto se non ti consente di rimanere pigro sulla distinzione tra i due. Potresti non essere sempre in grado di manipolare le stringhe, ma solo con Regex, quindi affidati alla memoria quella giusta e conosci la differenza!
dooleyo,

1
Non ho capito l'esempio con roba pericolosa perché in entrambi i casi si potrebbe includere roba pericolosa nella stringa, con o senza nuove righe sarebbe un exploit che dovrebbe essere risolto con sanificazione e convalida HTML.
Jayr Motta,

2
@JayrMotta quello che mostra la dimostrazione è che le cose pericolose aggirerebbero completamente l'intero controllo regex . Quindi, anche se stavi controllando cose pericolose nella tua regex, verrebbe aggirato se $controllassi la "fine della stringa" invece di \z.
Doctor Blue,

178

Secondo Piccone :

^ Corrisponde all'inizio di una riga.

$ Corrisponde alla fine di una riga.

\A Corrisponde all'inizio della stringa.

\z Corrisponde alla fine della stringa.

\Z Corrisponde alla fine della stringa a meno che la stringa non termini con a "\n", nel qual caso corrisponde appena prima di "\n".

Quindi, usa \Ae minuscole \z. Se usi \Zqualcuno, potresti intrufolarti in un personaggio newline. Questo non è pericoloso penso, ma potrebbe rovinare gli algoritmi che presumono che non ci siano spazi bianchi nella stringa. A seconda del regex e dei vincoli di lunghezza delle stringhe qualcuno potrebbe usare un nome invisibile con solo un carattere di nuova riga.

L'implementazione di JavaScript di Regex considera \Aletterale 'A'( ref ). Quindi guardati e prova.


16

L'inizio e la fine di una stringa potrebbero non coincidere necessariamente con l'inizio e la fine di una riga. Immagina se hai usato quanto segue come stringa di test:

il mio
nome
è
Andrew

Si noti che la stringa ha molte linee in esso - l' ^e $caratteri consentono di abbinare l'inizio e la fine di quelle linee (trattando fondamentalmente il \npersonaggio come un delimitatore), mentre \Ae \Zconsentono di adattare l'inizio e la fine della stringa.


1
La migliore risposta secondo me. "sostanzialmente trattando il carattere \ n come un delimitatore" mi ha davvero aiutato a capire, grazie.
Flyout91,

11

Differenza per esempio

  1. /^foo$/corrisponde a uno dei seguenti elementi /\Afoo\z/:
whatever1
foo
whatever2
foo
whatever2
whatever1
foo
  1. /^foo$/e /\Afoo\z/tutti corrispondono a quanto segue:
foo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.