2009-07-22 10 views
72

Biorąc pod uwagę tę funkcję:JavaScript zastąpić/regex

function Repeater(template) { 

    var repeater = { 

     markup: template, 

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

    }; 

    return repeater; 

}; 

Jak zrobić this.markup.replace() zastąpić globalnie? Oto problem. Jeśli używam go w ten sposób:

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

Wartość alertu to "foobar $ TEST_ONE".

Jeśli zmienię Repeater do dalszej, nic w zastąpiony w Chrome:

function Repeater(template) { 

    var repeater = { 

     markup: template, 

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

    }; 

    return repeater; 

}; 

... a wpisowi $TEST_ONE $TEST_ONE.

Odpowiedz

102

trzeba podwoić uciec żadnych znaków RegExp (raz na ukośnik w łańcuchu, a raz na regexp):

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

Inaczej wygląda to na końcu linii i „TestOne” (co nigdy nie znajdzie).

Osobiście nie jestem wielkim fanem budowania regexp za pomocą ciągów z tego powodu. Poziom ucieczki, który jest potrzebny, może doprowadzić cię do picia. Jestem pewien, że inni czują się inaczej i lubią pić przy pisaniu wyrażeń regularnych.

+0

Ale replace() odbiera regex jako zmienną. – core

+0

Drobna korekcja - '$' oznacza koniec wiersza w wyrażeniu regularnym. – harto

+6

@Chris - Nie sądzę, żeby to miało znaczenie, jeśli użyjesz '/ pattern /' lub 'new RegExp (" pattern ")'. – harto

21

Twój wzór regex powinny mieć g Modyfikator:

var pattern = /[somepattern]+/g; 

zawiadomienie G na końcu. mówi zamiennikowi, aby wykonał wymianę globalną.

Również nie musisz używać obiektu RegExp, który możesz zbudować jak powyżej. Przykład Wzór:

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

wzór jest zawsze otoczony/po obu stronach - z modyfikatorami po ostatecznym/G, modyfikatorów światowym.

EDYCJA: Dlaczego to ma znaczenie, jeśli wzór jest zmienną? W twoim przypadku będzie to działać tak (zauważyć, że wzór jest ciągle zmienna):

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

Ale trzeba byłoby zmienić zastąpić funkcję do tego:

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

w kategoriach interpretacji wzorca, nie ma różnicy między następujących formach:

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

Jeśli chcesz zastąpić ciągiem znaków przy użyciu metody replace, myślę, że można po prostu przejść ciąg zamiast regexp do replace.

W przeciwnym razie trzeba by uniknąć jakichkolwiek znaków specjalnych w wyrażeniach regularnych wzoru pierwszy - może tak:

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

// ... 

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

Nie wiedziałem wcześniej, że/pattern/jest taki sam jak nowy RegExp ("wzór"). Naprawdę pomogło! –

+1

Każdy powód, aby nie używać białej listy zamiast czarnej listy? np .: s.replace (/ (\ W)/g, '\\ $ 1') –

+1

Pierwszy wymieniony formularz jest lepszy. Dobrą praktyką jest unikanie słowa kluczowego _new_. – Druska