JavaScript thay thế / regex


113

Với chức năng này:

function Repeater(template) {

    var repeater = {

        markup: template,

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

    };

    return repeater;

};

Làm cách nào để this.markup.replace()thay thế 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 Repeaterthành phần sau thì không có gì được 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.

Câu trả lời:


147

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

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

Nếu không, nó sẽ tìm kiếm cuối dòng và 'TESTONE' (nó không bao giờ tìm thấy).

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


Nhưng Replace () nhận regex như một biến.
cốt lõi

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

@seth, Câu trả lời của bạn hoạt động, nhưng nó không cung cấp giải pháp cho mã từ OP. Làm cách nào để gọi mã OP?
Đen

82

Về mặt diễn giải mẫu, không có sự khác biệt giữa các dạng sau:

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

Nếu bạn muốn thay thế một chuỗi ký tự bằng cách sử dụng replacephương thức này, tôi nghĩ bạn có thể chỉ cần chuyển một chuỗi thay vì một regexp tới replace.

Nếu không, trước tiên bạn phải thoát khỏi bất kỳ ký tự đặc biệt regexp nào trong mẫu - 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);

12
Không biết trước đây, / pattern / giống như RegExp mới ("pattern"). Thực sự đã giúp!
Nik Sumeiko

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

1
Hình thức đầu tiên được liệt kê là tốt hơn. Thực hành tốt để tránh từ khóa mới .
Druska

2
Không chính xác khi nói rằng biểu thức chính quy (/ regex /) giống với RegExp ("regex"). Trong nghĩa đen của biểu thức chính quy, bản thân dấu gạch chéo ngược ('\') không cần phải thoát ('\\') để nó trở thành một phần của biểu thức chính quy. Hơn nữa, cụm từ biểu thức chính quy có thể được biên dịch khi tập lệnh được phân tích cú pháp thay vì mỗi khi hàm được thực thi. Để đối sánh với một dấu tích ngược, bạn có thể viết / \\ / hoặc RexExp ("\\\\").
John

31

Mẫu regex của bạn phải có công cụ sửa đổi g:

var pattern = /[somepattern]+/g;

chú ý chữ g ở cuối. nó yêu cầu người thay thế thực hiện thay thế toàn cầu.

Ngoài ra, bạn không cần 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ác bổ ngữ sau dấu cuối /, bổ ngữ g là tổng thể.

CHỈNH SỬA: Tại sao lại quan trọng nếu mẫu là một biến? Trong trường hợp của bạn, nó sẽ hoạt động như thế này (lưu ý rằng 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 thay đổi chức năng thay thế của mình thành:

this.markup = this.markup.replace(pattern, value);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.