Perbedaan antara \ A \ z dan ^ $ dalam ekspresi reguler Ruby

196

Dalam dokumentasi saya baca:

Gunakan \ A dan \ z untuk mencocokkan awal dan akhir string, ^ dan $ cocok dengan awal / akhir suatu baris.

Saya akan menerapkan ekspresi reguler untuk memeriksa nama pengguna (atau email sama) yang dikirimkan oleh pengguna. Ekspresi mana yang harus saya gunakan validates_format_ofdalam model? Saya tidak dapat memahami perbedaannya: Saya selalu menggunakan ^ dan $ ...

collimarco
sumber

Jawaban:

226

Jika Anda bergantung pada ekspresi reguler untuk validasi, Anda selalu ingin menggunakan \Adan \z. ^dan $hanya akan cocok hingga karakter baris baru, yang berarti mereka dapat menggunakan email seperti [email protected]\n<script>dangerous_stuff();</script>dan masih memvalidasi, karena regex hanya melihat semuanya sebelum\n .

Rekomendasi saya hanya akan menghapus baris baru dari nama pengguna atau email sebelumnya, karena tidak ada alasan yang sah untuk itu. Maka Anda dapat dengan aman menggunakan BAIK \A \zatau ^ $.

Luke
sumber
13
@ Ragmaanir benar, seharusnya dengan huruf kecil, \zbukan \Z!
Petr
10
+1 Terima kasih! Meskipun saya harus tidak setuju dengan rekomendasi Anda: A) Jangan menambahkan pekerjaan / pemrosesan yang tidak perlu jika ada tangkapan yang tepat, dan B) terutama tidak jika itu memungkinkan Anda untuk tetap malas membedakan antara keduanya. Anda mungkin tidak selalu berada dalam posisi untuk memanipulasi string, hanya untuk Regex, jadi lakukan yang benar ke memori dan ketahui bedanya!
dooleyo
1
Saya tidak mengerti contoh dengan hal-hal berbahaya karena dalam kedua kasus seseorang dapat memasukkan hal-hal berbahaya dalam string, dengan atau tanpa baris baru itu akan menjadi exploit yang harus diperbaiki dengan sanitasi html dan validasi.
Jayr Motta
2
@JayrMotta apa yang diperlihatkan demonstrasi adalah bahwa hal-hal berbahaya akan benar - benar melewati seluruh cek regex Anda . Jadi, bahkan jika Anda memeriksa hal-hal berbahaya di regex Anda, itu akan dilewati jika Anda biasa $memeriksa "end of string" \z.
Dokter Biru
177

Menurut Beliung :

^ Cocokkan dengan awal suatu garis.

$ Cocokkan dengan akhir baris.

\A Cocokkan dengan awal string.

\z Cocokkan dengan akhir string.

\Z Cocokkan ujung string kecuali string berakhir dengan a "\n", dalam hal ini cocok sebelum "\n".

Jadi, gunakan \Adan huruf kecil \z. Jika Anda menggunakan \Zseseorang, bisa menyelinap dalam karakter baris baru. Ini tidak berbahaya saya pikir, tetapi mungkin mengacaukan algoritma yang menganggap bahwa tidak ada spasi putih di string. Bergantung pada batasan regex dan string-length seseorang dapat menggunakan nama yang tidak terlihat hanya dengan karakter baris baru.

Implementasi Javascript dari Regex memperlakukan \Asebagai literal 'A'( ref ). Jadi jaga dirimu di luar sana dan uji.

Ragmaanir
sumber
16

Awal dan akhir suatu string mungkin tidak harus sama dengan awal dan akhir suatu garis. Bayangkan jika Anda menggunakan yang berikut ini sebagai string pengujian Anda:

saya
nama
adalah
Andrew

Perhatikan bahwa string memiliki banyak garis di dalamnya - karakter ^dan $memungkinkan Anda untuk mencocokkan awal dan akhir dari garis-garis tersebut (pada dasarnya memperlakukan \nkarakter sebagai delimeter) sementara \Adan \Zmemungkinkan Anda untuk mencocokkan awal dan akhir dari seluruh string.

Andrew Hare
sumber
1
Jawaban terbaik menurut saya. "pada dasarnya memperlakukan karakter sebagai delimeter" benar-benar membantu saya untuk mengerti, terima kasih.
Flyout91
11

Perbedaan Dengan Contoh

  1. /^foo$/cocok dengan yang berikut ini, /\Afoo\z/tidak:
whatever1
foo
whatever2
foo
whatever2
whatever1
foo
  1. /^foo$/dan /\Afoo\z/semua cocok dengan yang berikut ini:
foo
Chun Yang
sumber