2009-07-22 37 views
72

Với chức năng này:JavaScript thay thế/regex

function Repeater(template) { 

    var repeater = { 

     markup: template, 

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

    }; 

    return repeater; 

}; 

Làm thế nào để làm cho this.markup.replace() thay thế trên toàn cầu? Đây là vấn đề. Nếu tôi sử dụng nó như thế này:

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

Giá trị của cảnh báo là "foobar $ TEST_ONE".

Nếu tôi thay đổi Repeater đến những điều sau đây, sau đó không có gì trong thay thế trong Chrome:

function Repeater(template) { 

    var repeater = { 

     markup: template, 

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

    }; 

    return repeater; 

}; 

... và cảnh báo là $TEST_ONE $TEST_ONE.

Trả lời

102

Bạn cần phải thoát khỏi bất kỳ ký tự RegExp (một lần cho dấu gạch chéo trong chuỗi và một lần cho regexp) tăng gấp đôi:

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

Nếu không, nó sẽ tìm kiếm sự kết thúc của dòng và 'TESTONE' (mà nó không bao giờ tìm thấy).

Cá nhân, tôi không phải là người hâm mộ lớn xây dựng chuỗi sử dụng regexp vì lý do này. Mức độ thoát cần thiết có thể dẫn bạn uống. Tôi chắc rằng những người khác cảm thấy khác nhau và thích uống rượu khi viết regex.

+0

Nhưng replace() nhận regex như là một biến. – core

+0

Chỉnh sửa nhỏ - '$' biểu thị kết thúc của dòng trong một regexp. – harto

+6

@Chris - Tôi không nghĩ rằng nó tạo ra sự khác biệt nếu bạn sử dụng '/ pattern /' hoặc 'new RegExp ("pattern") '. – harto

21

mẫu biểu thức chính của bạn nên có g modifier:

var pattern = /[somepattern]+/g; 

thông báo g ở cuối. nó cho người thay thế thực hiện thay thế toàn cầu.

Ngoài ra, bạn không cần phải sử dụng đối tượng RegExp, bạn có thể tạo mẫu của mình như trên. Mẫu ví dụ:

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

một mẫu luôn được bao quanh bởi/ở hai bên - với công cụ sửa đổi sau lần cuối cùng /, công cụ sửa đổi g là toàn cục.

CHỈNH SỬA: Tại sao mẫu là biến? Trong trường hợp của bạn nó sẽ hoạt động như thế này (chú ý mẫu đó vẫn là một biến):

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

Nhưng bạn sẽ cần phải thay đổi thay của bạn chức năng sau:

this.markup = this.markup.replace(pattern, value); 
55

Xét về mô hình giải thích, không có sự khác biệt giữa các hình thức sau:

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

Nếu bạn muốn thay thế chuỗi ký tự bằng phương pháp replace, tôi nghĩ bạn chỉ có thể chuyển một chuỗi thay vì regexp đến replace.

Nếu không, bạn sẽ phải thoát khỏi bất kỳ ký tự đặc biệt regexp trong mô hình đầu tiên - có thể như vậy:

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

// ... 

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

Không biết trước đó, đó/mẫu/giống như RegExp mới ("mẫu"). Thực sự đã giúp! –

+1

Bất kỳ lý do nào để không sử dụng danh sách trắng thay vì danh sách đen? ví dụ: s.replace (/ (\ W)/g, '\\ $ 1') –

+1

Biểu mẫu đầu tiên được liệt kê tốt hơn. Thực hành tốt để tránh từ khóa _new_. – Druska