ความแตกต่างระหว่าง \ A \ z และ ^ $ ในนิพจน์ปกติของ Ruby


196

ในเอกสารที่ฉันอ่าน:

ใช้ \ A และ \ z เพื่อจับคู่จุดเริ่มต้นและจุดสิ้นสุดของสตริง, ^ และ $ ตรงกับจุดเริ่มต้น / สิ้นสุดของบรรทัด

ฉันจะใช้นิพจน์ทั่วไปเพื่อตรวจสอบชื่อผู้ใช้ (หรืออีเมลเหมือนกัน) ที่ส่งโดยผู้ใช้ ฉันควรใช้นิพจน์ใดvalidates_format_ofในโมเดล ฉันไม่เข้าใจความแตกต่าง: ฉันเคยใช้ ^ และ $ ...


คำตอบ:


226

หากคุณกำลังขึ้นอยู่กับการแสดงออกปกติสำหรับการตรวจสอบคุณก็ต้องการที่จะใช้และ\A และจะตรงกับขึ้นจนอักขระ newline ซึ่งหมายความว่าพวกเขาสามารถใช้อีเมลชอบและยังคงมีการตรวจสอบมันตั้งแต่ regex เพียงเห็นทุกอย่างก่อน\z^$me@example.com\n<script>dangerous_stuff();</script>\n

คำแนะนำของฉันจะลอกบรรทัดใหม่จากชื่อผู้ใช้หรืออีเมลไว้ล่วงหน้าอย่างสมบูรณ์เนื่องจากไม่มีเหตุผลที่ถูกต้อง จากนั้นคุณสามารถใช้หรือ\A \z^ $


13
@ Ragmaanir ถูกต้องมันควรจะเป็นตัวอักษรเล็ก ๆ\zแทน \Z!
Petr

11
+1 ขอบคุณ! แม้ว่าฉันจะไม่เห็นด้วยกับข้อเสนอแนะของคุณ: A) อย่าเพิ่มงาน / การประมวลผลที่ไม่จำเป็นหากมี catch-all ที่เหมาะสมและ B) โดยเฉพาะถ้ามันช่วยให้คุณขี้เกียจเกี่ยวกับการแยกแยะระหว่างสองคนนี้ คุณอาจไม่ได้อยู่ในตำแหน่งที่จะจัดการกับสายอักขระได้เฉพาะกับ Regex เท่านั้นดังนั้นให้ส่งสายที่ถูกต้องไปยังหน่วยความจำและทราบถึงความแตกต่าง!
dooleyo

1
ฉันไม่เข้าใจตัวอย่างของสิ่งที่เป็นอันตรายเพราะในกรณีใดกรณีหนึ่งอาจรวมถึงสิ่งที่เป็นอันตรายในสตริงโดยมีหรือไม่มีบรรทัดใหม่มันจะเป็นการหาประโยชน์ที่ควรได้รับการแก้ไขด้วย html sanitizing และการตรวจสอบความถูกต้อง
Jayr Motta

2
@JayrMotta สิ่งที่แสดงให้เห็นการสาธิตคือว่าสิ่งที่เป็นอันตรายจะสมบูรณ์ข้ามการตรวจสอบ regex ทั้งหมดของคุณ ดังนั้นแม้ว่าคุณจะได้รับการตรวจสอบสิ่งที่เป็นอันตรายใน regex ของคุณก็จะได้รับการข้ามถ้าคุณใช้$ในการตรวจสอบ "จุดสิ้นสุดของสตริง" \zแทน
Doctor Blue

178

ตามPickaxe :

^ ตรงกับจุดเริ่มต้นของบรรทัด

$ จับคู่ส่วนท้ายของบรรทัด

\A ตรงกับจุดเริ่มต้นของสตริง

\z จับคู่ส่วนท้ายของสตริง

\Z ตรงกับจุดสิ้นสุดของสตริงเว้นแต่สตริงจบลงด้วยการที่ซึ่งในกรณีนี้มันตรงกับก่อน"\n""\n"

ดังนั้นการใช้งานและตัวพิมพ์เล็ก\A \zหากคุณใช้\Zใครบางคนสามารถแอบเป็นตัวละครขึ้นบรรทัดใหม่ ฉันคิดว่ามันไม่อันตราย แต่อาจทำให้อัลกอริทึมที่คิดว่าไม่มีช่องว่างในสตริง ขึ้นอยู่กับข้อ จำกัด regex และความยาวสตริงของคุณบางคนสามารถใช้ชื่อที่มองไม่เห็นด้วยอักขระขึ้นบรรทัดใหม่

การใช้ Regex ของ JavaScript ถือ\Aเป็นตัวอักษร'A'( ref ) ดังนั้นระวังตัวเองออกไปและทดสอบ


16

จุดเริ่มต้นและจุดสิ้นสุดของสตริงอาจไม่จำเป็นต้องเป็นสิ่งเดียวกันกับจุดเริ่มต้นและจุดสิ้นสุดของบรรทัด ลองนึกภาพถ้าคุณใช้สิ่งต่อไปนี้เป็นชุดทดสอบ:

ฉัน
ชื่อ
คือ
แอนดรู

ขอให้สังเกตว่าสตริงมีหลายบรรทัดในนั้น - ^และ$ตัวอักษรช่วยให้คุณสามารถจับคู่จุดเริ่มต้นและจุดสิ้นสุดของบรรทัดเหล่านั้น (โดยทั่วไปถือว่า\nอักขระเป็น delimeter) ในขณะที่\Aและ\Zให้คุณจับคู่จุดเริ่มต้นและจุดสิ้นสุดของสตริงทั้งหมด


1
คำตอบที่ดีที่สุดในความคิดของฉัน "โดยพื้นฐานแล้วการรักษาตัวละคร \ n เป็นขอบเขต" ช่วยให้ฉันเข้าใจจริงๆขอบคุณ
Flyout91

11

ความแตกต่างตามตัวอย่าง

  1. /^foo$/ตรงกับข้อใดข้อหนึ่งต่อไปนี้/\Afoo\z/ไม่ได้:
whatever1
foo
whatever2
foo
whatever2
whatever1
foo
  1. /^foo$/และ/\Afoo\z/ตรงทั้งหมดต่อไปนี้:
foo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.