JavaScript แทนที่ / regex


113

ให้ฟังก์ชันนี้:

function Repeater(template) {

    var repeater = {

        markup: template,

        replace: function(pattern, value) {
            this.markup = this.markup.replace(pattern, value);
        }

    };

    return repeater;

};

ฉันจะทำการthis.markup.replace()แทนที่ทั่วโลกได้อย่างไร นี่คือปัญหา ถ้าฉันใช้แบบนี้:

alert(new Repeater("$TEST_ONE $TEST_ONE").replace("$TEST_ONE", "foobar").markup);

ค่าของการแจ้งเตือนคือ "foobar $ TEST_ONE"

หากฉันเปลี่ยนRepeaterสิ่งต่อไปนี้จะไม่มีสิ่งใดมาแทนที่ใน Chrome:

function Repeater(template) {

    var repeater = {

        markup: template,

        replace: function(pattern, value) {
            this.markup = this.markup.replace(new RegExp(pattern, "gm"), value);
        }

    };

    return repeater;

};

... $TEST_ONE $TEST_ONEและการแจ้งเตือนคือ

คำตอบ:


147

คุณต้องใช้ Escape อักขระ RegExp สองครั้ง (หนึ่งครั้งสำหรับเครื่องหมายทับในสตริงและอีกครั้งสำหรับ regexp):

  "$TESTONE $TESTONE".replace( new RegExp("\\$TESTONE","gm"),"foo")

มิฉะนั้นจะมองหาจุดสิ้นสุดของบรรทัดและ "TESTONE" (ซึ่งไม่เคยพบ)

โดยส่วนตัวแล้วฉันไม่ใช่แฟนตัวยงของการสร้าง regexp โดยใช้สตริงด้วยเหตุผลนี้ ระดับการหลบหนีที่จำเป็นอาจทำให้คุณดื่มได้ ฉันแน่ใจว่าคนอื่น ๆ รู้สึกไม่เหมือนกันและชอบดื่มเมื่อเขียน regexes


แต่แทนที่ () ได้รับ regex เป็นตัวแปร
core

8
@ Chris - ฉันไม่คิดว่ามันทำให้ความแตกต่างถ้าคุณใช้หรือ/pattern/ new RegExp("pattern")
harto

@seth คำตอบของคุณใช้งานได้ แต่ไม่มีคำตอบสำหรับโค้ดจาก OP ฉันต้องเรียกรหัสของ OP อย่างไร?
Black

82

ในแง่ของการตีความรูปแบบไม่มีความแตกต่างระหว่างรูปแบบต่อไปนี้:

  • /pattern/
  • new RegExp("pattern")

หากคุณต้องการแทนที่สตริงตามตัวอักษรโดยใช้replaceวิธีนี้ฉันคิดว่าคุณสามารถส่งสตริงแทน regexp ไปreplaceได้

มิฉะนั้นคุณจะต้องหลีกเลี่ยงอักขระพิเศษ regexp ในรูปแบบก่อน - อาจเป็นเช่นนั้น:

function reEscape(s) {
    return s.replace(/([.*+?^$|(){}\[\]])/mg, "\\$1");
}

// ...

var re = new RegExp(reEscape(pattern), "mg");
this.markup = this.markup.replace(re, value);

12
ไม่ทราบมาก่อนว่า / pattern / เหมือนกับ RegExp ใหม่ ("pattern") ช่วยได้จริงๆ!
Nik Sumeiko

1
มีเหตุผลอะไรที่จะไม่ใช้รายการที่อนุญาตพิเศษแทนบัญชีดำ? เช่น: s.replace (/ (\ W) / g, '\\ $ 1')
greg.kindel

1
แบบฟอร์มแรกที่ระบุไว้จะดีกว่า เป็นแนวทางปฏิบัติที่ดีในการหลีกเลี่ยงคำหลักใหม่
Druska

2
ไม่ถูกต้องที่จะบอกว่านิพจน์ทั่วไปลิเทอรัล (/ regex /) เหมือนกับ RegExp ("regex") ในนิพจน์ทั่วไปลิเทอรัล reverse-solidus ('\') ไม่จำเป็นต้องมีการ Escape ('\\') เพื่อให้เป็นส่วนหนึ่งของนิพจน์ทั่วไป นอกจากนี้ยังสามารถคอมไพล์ลิเทอรัลนิพจน์ทั่วไปได้เมื่อสคริปต์ถูกแยกวิเคราะห์ไม่ใช่ทุกครั้งที่เรียกใช้ฟังก์ชัน ในการจับคู่ reverse-solidus คุณสามารถเขียน / \\ / หรือ RexExp ("\\\\")
John

31

รูปแบบ regex ของคุณควรมีตัวปรับ g:

var pattern = /[somepattern]+/g;

สังเกตเห็น g ในตอนท้าย จะบอกให้ผู้แทนที่ทำการแทนที่ทั่วโลก

นอกจากนี้คุณไม่จำเป็นต้องใช้วัตถุ RegExp คุณสามารถสร้างรูปแบบของคุณได้ตามด้านบน รูปแบบตัวอย่าง:

var pattern = /[0-9a-zA-Z]+/g;

รูปแบบจะล้อมรอบด้วย / ด้านใดด้านหนึ่งเสมอ - ด้วยตัวปรับแต่งหลังสุดท้าย / ตัวปรับ g จะเป็นโกลบอล

แก้ไข:ทำไมถึงสำคัญว่ารูปแบบเป็นตัวแปร? ในกรณีของคุณมันจะทำงานเช่นนี้ (สังเกตว่ารูปแบบยังคงเป็นตัวแปร):

var pattern = /[0-9a-zA-Z]+/g;
repeater.replace(pattern, "1234abc");

แต่คุณจะต้องเปลี่ยนฟังก์ชันการแทนที่ของคุณเป็นสิ่งนี้:

this.markup = this.markup.replace(pattern, value);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.