เครื่องมือข้อความและชีวิตประจำวัน · ชุดเครื่องมือข้อความ
ทำไม ^ และ $ ตรงกันเพียงครั้งเดียว: การตั้งค่าสถานะ regex ในเบราว์เซอร์ค้นหาและแทนที่
· มันทำงานอย่างไร
การแสดงออกปกติ ค้นหาและแทนที่ การล้างข้อความ
อธิบาย JavaScript แฟล็ก regex - global, multiline และ dotAll - และเหตุใดกล่องค้นหาและแทนที่จึงคอมไพล์โดยไม่มีจุดยึดหลายบรรทัด ^ และ $ สำหรับข้อความทั้งหมด โดยมีรูปแบบที่ใช้แทน
รูปแบบที่แก้ไขเฉพาะบรรทัดแรก — จะเกิดอะไรขึ้นเมื่อคุณคาดหวังว่า ^ จะหมายถึง 'จุดเริ่มต้นของแต่ละบรรทัด'
รายการที่วางอาจมีคำนำหน้าที่ไม่ต้องการเหมือนกันในทุกแถว แต่การค้นหา `^prefix` จะลบออกจากแถวแรกเท่านั้น ผลลัพธ์ที่น่าประหลาดใจมาจากการกำหนดค่ารูปแบบ ไม่ใช่จากข้อมูลที่ไม่สอดคล้องกัน ใน ToolAcre นั้น `^` ระบุจุดเริ่มต้นของข้อความที่สมบูรณ์ เนื่องจากนิพจน์ทั่วไปถูกคอมไพล์โดยไม่มีโหมดหลายบรรทัด
จุดยึด `$` ที่ตรงกันจะเป็นไปตามกฎเดียวกันที่ขอบอีกด้านหนึ่ง โดยจะระบุจุดสิ้นสุดของข้อความทั้งหมด ไม่ใช่ทุกบรรทัดที่สิ้นสุดภายในนั้น ตัวแบ่งบรรทัดยังคงเป็นส่วนหนึ่งของอินพุต แต่จะไม่กลายเป็นตำแหน่งจุดยึดอื่น ตรวจสอบจำนวนการเปลี่ยนที่รายงานก่อนที่จะนำเข้ารายการที่ล้างแล้ว การนับหนึ่งจะทำให้ข้อมูลไม่ตรงกันทันที
ธง g — เหตุใด 'แทนที่ทุกการแข่งขันในการผ่านครั้งเดียว' ขึ้นอยู่กับการตั้งค่าสถานะสากล
ToolAcre สร้างรูปแบบการค้นหาด้วยแฟล็ก `g` ทั่วโลกเสมอ ตัวเลือกนั้นจะบอก JavaScript ให้รวบรวมทุกการแข่งขันที่ไม่ทับซ้อนกัน แทนที่จะหยุดหลังจากนัดแรก ขั้นแรกเครื่องมือจะเรียก `match` เพื่อกำหนดจำนวน จากนั้นส่งผ่านรูปแบบสากลเดียวกันไปยัง `replace` ดังนั้นหมายเลขที่แสดงและการส่งผ่านแทนที่จะใช้กฎเดียวที่ตรงกัน
การจับคู่ทั่วโลกไม่สามารถสร้างตำแหน่งที่รูปแบบไม่รู้จักได้ ด้วย `^prefix` มีเพียงข้อความเริ่มต้นที่มีสิทธิ์เพียงรายการเดียวเท่านั้น ดังนั้น `g` จึงยังคงพบรายการที่ตรงกันเพียงรายการเดียว ด้วยรูปแบบที่สามารถเกิดขึ้นได้ในหลายแถว `g` อนุญาตให้แทนที่เหตุการณ์ทั้งหมดได้ แยกคำถามเหล่านี้ออกเมื่อทำการแก้ไขจุดบกพร่อง: จุดยึดจะตัดสินใจว่าการแข่งขันจะเริ่มต้นที่ใด ในขณะที่โหมดสากลจะตัดสินใจว่าการค้นหาจะดำเนินต่อไปหรือไม่
ธง m — การเปลี่ยนแปลงหลายบรรทัด ^ และ $ จากจุดยึดข้อความทั้งหมดไปเป็นจุดยึดบรรทัดอย่างไร และเหตุใดเครื่องมือนี้จึงละทิ้งไป
แฟล็ก `m` แบบหลายบรรทัดจะเปลี่ยนวิธีการตีความ `^` และ `$` ช่วยให้สามารถจดจำตำแหน่งรอบจุดสิ้นสุดของบรรทัดตลอดจนขอบเขตข้อความด้านนอก ToolAcre ไม่ได้เพิ่มการตั้งค่าสถานะนั้น คอมไพเลอร์ใช้ `g` สำหรับการค้นหาที่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ และ `gi` เมื่อล้างการพิจารณาตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ โดยไม่มีการควบคุมผู้ใช้สำหรับการตั้งค่าสถานะเพิ่มเติม
การปล่อยให้หลายบรรทัดไม่พร้อมใช้งานจะทำให้อินเทอร์เฟซมีขนาดเล็ก แต่หมายความว่ารูปแบบที่คัดลอกมาจากโปรแกรมแก้ไขที่กำหนดค่าด้วย `gm` อาจทำงานแตกต่างออกไปที่นี่ อย่าคิดว่าสำนวนที่คุ้นเคยมีแฟล็กติดตัวไปด้วย JavaScript จะมีการจัดเตรียมตัวอักษรแฟล็กเมื่อมีการสร้าง RegExp และเครื่องมือนี้จะปฏิเสธไวยากรณ์แฟล็กอินไลน์ที่ไม่สนับสนุน แทนที่จะเปิดใช้งานโหมดอื่นโดยไม่ต้องแจ้งให้ทราบ
ธง s — เหตุใดจุดจึงไม่ตรงกับการขึ้นบรรทัดใหม่ตามค่าเริ่มต้น และวิธีจับคู่ข้ามบรรทัดโดยไม่มีจุดดังกล่าว
จุดในเครื่องมือนี้ไม่ตรงกับการขึ้นบรรทัดใหม่ เนื่องจากคอมไพเลอร์ละเว้นแฟล็ก dotAll `s` ด้วย รูปแบบ เช่น `BEGIN.*END` สามารถจับคู่ได้เมื่อเครื่องหมายทั้งสองอยู่บนบรรทัดเดียว แต่จะหยุดที่ตัวแบ่งบรรทัดแรกเมื่อเครื่องหมายขยายหลายแถว การเพิ่มโหมดสากลไม่ได้เปลี่ยนแปลงสิ่งที่จุดนั้นสามารถใช้ได้
เมื่อจำเป็นต้องมีการจับคู่แบบข้ามบรรทัดอย่างแท้จริง ให้เขียนอักขระที่ได้รับอนุญาตอย่างชัดเจน คลาสเช่น `[\s\S]*?` สามารถขยายช่องว่างและไม่ใช่ช่องว่างได้ในขณะที่ยังคงไม่เต็มใจ แม้ว่ารูปแบบกว้างๆ สมควรได้รับการทดสอบกับตัวอย่างเล็กๆ ก่อน คอมไพเลอร์จับไวยากรณ์ที่ไม่ถูกต้อง แต่ไม่ได้ป้องกันแท็บจากนิพจน์ราคาแพงที่มีพฤติกรรมย้อนรอยอย่างรุนแรง
การจับคู่บรรทัดใหม่อย่างชัดเจน — การใช้ \n ในรูปแบบเพื่อกำหนดเป้าหมายบรรทัดจะเริ่มต้นและสิ้นสุดเมื่อหลายบรรทัดไม่พร้อมใช้งาน
สำหรับการขึ้นบรรทัดซ้ำโดยไม่มีโหมดหลายบรรทัด ให้จับคู่จุดเริ่มต้นของข้อความหรือการขึ้นบรรทัดใหม่: `(^|\n)prefix` ทางเลือกแรกจัดการแถวแรก และทางเลือกที่สองจัดการแถวหลังโดยใช้การขึ้นบรรทัดใหม่ก่อนหน้า วงเล็บจะจับขอบเขตใดก็ตามที่ตรงกัน ทำให้การแทนที่มีวิธีการรักษาโครงสร้างที่แยกเส้นออกจากกัน
เทคนิคนี้ถือว่าตัวแยกการป้อนบรรทัดในรูปแบบ ไลบรารีข้อความรู้จัก CRLF, LF และ lone CR เมื่อดำเนินการบรรทัดเฉพาะ แต่ค้นหาและแทนที่การค้นหาสตริงต้นฉบับโดยตรง หากเนื้อหาที่วางใช้รูปแบบการลงท้ายบรรทัดอื่น ให้ทำให้เป็นมาตรฐานก่อนหรือจงใจปรับนิพจน์ มิฉะนั้นแถวต่อๆ ไปอาจยังคงไม่ถูกแตะต้องแม้ว่าจะดูเหมือนกันบนหน้าจอก็ตาม
จับคู่ขอบเขตเส้นอย่างชัดเจนด้วย (^|\n) และรักษาตัวคั่นที่บันทึกไว้
สมมติว่าอินพุตคือ `ID: apple`, `ID: pear` และ `ID: plum` บนบรรทัดแยกกัน เปิดใช้งาน Regex ค้นหา `(^|\n)ID: ` และแทนที่ด้วย `$1` ในแถวแรก `$1` คือตำแหน่งเริ่มต้นว่าง ในแถวหลังๆ จะเป็นบรรทัดใหม่ที่บันทึกไว้ ป้ายกำกับจะหายไปในขณะที่ขอบเขตทั้งสามแถวยังคงอยู่
อ่านจำนวนการเปลี่ยนก่อนที่จะยอมรับผลลัพธ์ สามแถวควรสร้างการแทนที่สามครั้งในตัวอย่างนี้ หากนับเป็นหนึ่ง ให้ตรวจสอบรูปแบบและการสิ้นสุดบรรทัดจริง แทนที่จะทำซ้ำขั้นตอนนี้ การเลิกทำจะพร้อมใช้งานหลังจากการแทนที่ ดังนั้นการทดลองใช้เล็กน้อยจึงสามารถยืนยันทั้งการจับคู่และการสร้างใหม่ก่อนที่นิพจน์เดียวกันจะแตะรายการนำเข้าที่ยาวกว่า
สิ่งนี้ไม่ครอบคลุมถึง - แฟล็ก u, i และ y และการแทรกบรรทัดใหม่ในการแทนที่ ซึ่งฟิลด์บรรทัดเดียวไม่สามารถทำได้
การใช้งานยังใช้ `i` เมื่อปิดการพิจารณาตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ แต่ไม่มีการเปิดเผยการควบคุมสำหรับ `u`, `y`, `m` หรือ `s` บทความนี้ไม่ได้กำหนดลักษณะการทำงานให้กับโหมดที่ไม่พร้อมใช้งานเหล่านั้น นอกเหนือจากการอธิบายเอฟเฟกต์หลายบรรทัดและ dotAll ที่ขาดหายไปที่จำเป็นสำหรับตัวอย่าง รูปแบบจากสภาพแวดล้อม JavaScript อื่นจะต้องได้รับการตรวจสอบเทียบกับแฟล็กที่ ToolAcre คอมไพล์จริง ๆ
แหล่งที่มาพิสูจน์ว่าข้อความแทนที่ถูกส่งไปที่ JavaScript `String.replace` ดังนั้นการแทนที่เช่น `$1`, `$&` และ `$$` ยังคงความหมาย JavaScript ไว้ ไม่ได้สร้างทุกการโต้ตอบที่นำเสนอโดยฟิลด์ที่แสดงผลจากไฟล์ที่ใช้ที่นี่ โดยเฉพาะอย่างยิ่ง การแทรกบรรทัดใหม่ทางกายภาพผ่านอินเทอร์เฟซควรได้รับการทดสอบ แทนที่จะอนุมานจากโครงร่างเพียงอย่างเดียว
แฟล็กและลักษณะการทำงานของฟิลด์การแทนที่อื่นๆ อยู่นอกเหนือการใช้งานเครื่องมือนี้
ถือว่าแฟล็กเป็นส่วนหนึ่งของนิพจน์ทั่วไป แม้ว่าอินเทอร์เฟซจะแสดงเฉพาะเนื้อหารูปแบบก็ตาม ใน ToolAcre การค้นหาทุกครั้งจะเป็นแบบสากล โหมดที่ไม่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่จะเพิ่ม `i` และไม่มีหลายบรรทัดและ dotAll ข้อเท็จจริงเหล่านั้นอธิบายว่าทำไมการแทนที่จึงดำเนินต่อไปในการแข่งขันทั่วไป ในขณะที่ `^`, `$` และ dot ยังคงรักษาข้อจำกัดเริ่มต้นของข้อความทั้งหมดและบรรทัดเดียว
สำหรับรายการที่วางคำนำหน้า `(^|\n)prefix` ที่มี `$1` เป็นวิธีการแก้ปัญหาเชิงปฏิบัติ เนื่องจากเป็นการตั้งชื่อขอบเขตและเก็บรักษาไว้ เริ่มต้นด้วยแถวตัวแทน ยืนยันการนับ ตรวจสอบโครงสร้างบรรทัดผลลัพธ์ จากนั้นจึงประมวลผลชุดข้อมูลทั้งหมดเท่านั้น ขั้นตอนดังกล่าวจะเปลี่ยนผลลัพธ์การแข่งขันนัดเดียวที่น่าสงสัยให้เป็นขั้นตอนการล้างข้อมูลที่ตรวจสอบได้ก่อนที่จะนำเข้า