Różnica między \ A \ z i ^ $ w wyrażeniach regularnych Ruby


196

W dokumentacji czytam:

Użyj \ A i \ z, aby dopasować początek i koniec łańcucha, ^ i $ dopasuj początek / koniec linii.

Zamierzam zastosować wyrażenie regularne, aby sprawdzić nazwę użytkownika (lub adres e-mail jest taki sam) przesłaną przez użytkownika. Z jakim wyrażeniem powinienem korzystać validates_format_ofw modelu? Nie rozumiem różnicy: zawsze używałem ^ i $ ...


Odpowiedzi:


226

Jeśli zależysz od wyrażenia regularnego do sprawdzania poprawności, zawsze chcesz użyć \Ai \z. ^i $będą pasować tylko do znaku nowej linii, co oznacza, że ​​mogą użyć wiadomości e-mail podobnej do tej me@example.com\n<script>dangerous_stuff();</script>i nadal ją sprawdzać, ponieważ regex widzi wszystko tylko przed \n.

Moim zaleceniem byłoby po prostu całkowite usunięcie nowych wierszy z nazwy użytkownika lub e-maila, ponieważ nie ma prawie żadnego uzasadnionego powodu. Następnie możesz bezpiecznie używać EITHER \A \zlub ^ $.


13
@Ragmaanir ma rację, powinien być z małą literą \zzamiast \Z!
Petr

10
+1 dzięki! Chociaż musiałbym się nie zgodzić z twoją rekomendacją: A) Nie dodawaj niepotrzebnej pracy / przetwarzania, jeśli jest odpowiedni catch-all, i B) szczególnie nie, jeśli pozwala ci to pozostać leniwym w rozróżnianiu tych dwóch. Nie zawsze możesz być w stanie manipulować sznurkiem, tylko do Regex, więc zapisz odpowiednią pamięć i poznaj różnicę!
dooleyo

1
Nie rozumiałem przykładu z niebezpiecznymi rzeczami, ponieważ w obu przypadkach można było włączyć niebezpieczne rzeczy do łańcucha, z nowymi liniami lub bez nich, byłby to exploit, który powinien zostać naprawiony poprzez odkażanie i sprawdzanie poprawności HTML.
Jayr Motta

2
@JrrMotta pokazuje, że pokaz pokazuje, że niebezpieczne rzeczy całkowicie ominęłyby cały test wyrażenia regularnego . Więc nawet jeśli sprawdzasz w swoim wyrażeniu regularnym niebezpieczne rzeczy, zostanie ono pominięte, jeśli $zamiast tego użyjesz „końca łańcucha” \z.
Doctor Blue

177

Według Pickaxe :

^ Dopasowuje początek linii.

$ Dopasowuje koniec linii.

\A Dopasowuje początek łańcucha.

\z Dopasowuje koniec łańcucha.

\Z Dopasowuje koniec łańcucha, chyba że łańcuch kończy się na a "\n", w którym to przypadku dopasowuje się tuż przed znakiem "\n".

Więc używaj \Ai małe litery \z. Jeśli używasz, \Zktoś może się zakraść w znaku nowej linii. Myślę, że nie jest to niebezpieczne, ale może zepsuć algorytmy, które zakładają, że w łańcuchu nie ma białych znaków. W zależności od ograniczeń wyrażenia regularnego i długości łańcucha ktoś może użyć niewidzialnej nazwy z tylko znakiem nowej linii.

Implementacja JavaScript w Regex traktuje \Ajak literał 'A'( ref ). Uważaj więc na siebie i testuj.


16

Początek i koniec łańcucha niekoniecznie musi być tym samym, co początek i koniec linii. Wyobraź sobie, że wykorzystałeś następujące parametry jako ciąg testowy:

moje
nazwisko
jest
Andrew

Zauważ, że ciąg ma wiele wierszy - znaki ^i $pozwalają dopasować początek i koniec tych wierszy (zasadniczo traktując \nznak jako ogranicznik), \Aa jednocześnie \Zpozwalają dopasować początek i koniec całego łańcucha.


1
Najlepsza odpowiedź moim zdaniem. „Zasadniczo traktowanie znaku \ n jako ogranicznika” naprawdę pomogło mi zrozumieć, dziękuję.
Flyout91

11

Różnica według przykładu

  1. /^foo$//\Afoo\z/spełnia którekolwiek z poniższych kryteriów, nie:
whatever1
foo
whatever2
foo
whatever2
whatever1
foo
  1. /^foo$/i /\Afoo\z/wszystkie pasują do następujących:
foo
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.