Jak używać zmiennej w wyrażeniu regularnym?


1377

Chciałbym stworzyć String.replaceAll()metodę w JavaScript i myślę, że użycie wyrażenia regularnego byłoby najkrótszym sposobem na zrobienie tego. Nie mogę jednak wymyślić, jak przekazać zmienną do wyrażenia regularnego. Mogę to zrobić już, która zastąpi wszystkie wystąpienia "B"z "A".

"ABABAB".replace(/B/g, "A");

Ale chcę zrobić coś takiego:

String.prototype.replaceAll = function(replaceThis, withThis) {
    this.replace(/replaceThis/g, withThis);
};

Ale oczywiście zastąpi to tylko tekst "replaceThis"... więc jak przekazać tę zmienną do mojego łańcucha wyrażeń regularnych?


9
Pamiętaj, że obecnie pracujemy nad dodaniem tej funkcji do JavaScript, jeśli masz na jej temat opinię, dołącz do dyskusji.
— Benjamin Gruenbaum,

Odpowiedzi:


1839

Zamiast używać /regex/gskładni, możesz zbudować nowy obiekt RegExp :

var replace = "regex";
var re = new RegExp(replace,"g");

W ten sposób można dynamicznie tworzyć obiekty wyrażeń regularnych. Następnie zrobisz:

"mystring".replace(re, "newstring");

272
Jeśli trzeba użyć wyrazem jak /\/word\:\w*$/należy uciec swoje backslashy: new RegExp( '\\/word\\:\\w*$' ).
— Jonathan Swinney,

2
@gravityboy Możesz zrobić ('' + myNumber) .replace (/ 10 / g, 'a') lub jeśli chcesz liczb szesnastkowych, możesz zrobić parseInt ('' + myNumber, 16), aby przekonwertować na szesnastkowy z dziesiętnego.
— Eric Wendelin,

29
Pytanie sugeruje, że RegEx służy wyłącznie do ciągłego zastępowania łańcucha. Tak więc odpowiedź jest błędna, ponieważ zawiodłaby, gdyby ciąg znaków zawierał meta RegEx.
— Niestety,

16
Przykład przekazania zmiennej może być dobrą odpowiedzią. Nadal walczę po przeczytaniu tego.
— Goose

3
@JathanathanSwinney: /nie ma specjalnego znaczenia, jeśli konstruujesz wyrażenie regularne z łańcucha, więc nie musisz przed nim uciekać. /\/word\:\w*$/powinien byćnew RegExp('/word\\:\\w*$')
— Dávid Horváth,

211

Jak wspomniał Eric Wendelin, możesz zrobić coś takiego:

str1 = "pattern"
var re = new RegExp(str1, "g");
"pattern matching .".replace(re, "regex");

To daje "regex matching .". Jednak zakończy się niepowodzeniem, jeśli str1 jest ".". Można się spodziewać, że wynik będzie "pattern matching regex", zastępując kropkę "regex", ale okaże się, że ...

regexregexregexregexregexregexregexregexregexregexregexregexregexregexregexregexregexregex

Wynika to z faktu, że chociaż "."jest ciągiem, w konstruktorze RegExp jest nadal interpretowany jako wyrażenie regularne, co oznacza dowolny znak nieliniowy, oznaczający każdy znak w ciągu. W tym celu przydatna może być następująca funkcja:

 RegExp.quote = function(str) {
     return str.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
 };

Następnie możesz zrobić:

str1 = "."
var re = new RegExp(RegExp.quote(str1), "g");
"pattern matching .".replace(re, "regex");

poddający się "pattern matching regex".


4
Wiesz, że pierwszym parametrem do zamiany może być normalny ciąg znaków i nie musi to być wyrażenie regularne? str1 = "."; alert („dopasowanie wzorca.”. replace (str1, „string”));
— jakieś

@some: oczywiście. To dlatego, że powyższy przykład jest trywialny. Kiedy musisz wyszukać lub zastąpić wzorzec połączony ze zwykłym łańcuchem, wykonaj str.match (nowy RegExp („https?: //” + RegExp.escape (mojaDomenaNazwa)), na przykład denerwujące, że funkcja ucieczki jest niewbudowany.
— Gracenotes,

(ciąg dalszy) Plus, najwyraźniej JC Grubbs wymagał globalnej wymiany; implementacja globalnego zastąpienia za pomocą String.replace (String, String) może być powolna w przypadku dużych danych wejściowych. Mówię tylko, że dwa najlepsze rozwiązania są błędne i przy niektórych danych wejściowych nieoczekiwanie zakończą się niepowodzeniem.
— Gracenotes

4
developer.mozilla.org/en-US/docs/JavaScript/Guide/… oferuje podobną funkcję, ale wyklucza -i obejmuje =!:/.
— chbrown

8
Prawidłowy termin to „ucieczka”, a nie „cytat”. Tylko BTW.
— Lawrence Dol

118

"ABABAB".replace(/B/g, "A");

Jak zawsze: nie używaj wyrażenia regularnego, chyba że musisz. W przypadku prostej zamiany ciągu idiomem jest:

'ABABAB'.split('B').join('A')

Nie musisz się więc martwić o kwestie cytowania wspomniane w odpowiedzi Gracenotes.


11
A czy zmierzyłeś, że jest to szybsze niż wyrażenie regularne?
— Mitar

3
Wydaje się to preferowane, szczególnie gdy trzeba dopasować specjalne znaki regularne, takie jak „.”
— Krease

1
Uhm ... Nie dzieli również wziąć RegExp; jeśli tak, to czy nie spowodowałoby tego samego problemu? W każdym razie ... .split (). Join () może działać wolniej na niektórych platformach, ponieważ są to dwie operacje, podczas gdy .replace () jest jedną operacją i może być zoptymalizowana.

5
@ PacMan--: oba spliti replacemogą przyjmować ciąg znaków lub RegExpobiekt. Problem, replacektóry tego splitnie robi, polega na tym, że gdy używasz łańcucha, dostajesz tylko jedną zamiennik.
— bobince


38

Jeśli chcesz uzyskać WSZYSTKIE wystąpienia ( g), nie rozróżniaj wielkości liter ( i) i używaj granic, aby nie było to słowo w innym słowie ( \\b):

re = new RegExp(`\\b${replaceThis}\\b`, 'gi');

Przykład:

let inputString = "I'm John, or johnny, but I prefer john.";
let replaceThis = "John";
let re = new RegExp(`\\b${replaceThis}\\b`, 'gi');
console.log(inputString.replace(re, "Jack")); // I'm Jack, or johnny, but I prefer Jack.

Dziękuję Ci! (afaict, twoja jest jedyną odpowiedzią jednoznacznie z rxinterpolacją Emacs / styl, za pomocą ciągów szablonów.)
— sam boosalis

34

Dla każdego, kto chce użyć zmiennej z metodą dopasowania , to zadziałało dla mnie

var alpha = 'fig';
'food fight'.match(alpha + 'ht')[0]; // fight


20
this.replace( new RegExp( replaceThis, 'g' ), withThis );

Podoba mi się ta odpowiedź, ponieważ nie tworzy dodatkowej (i bezcelowej) zmiennej.
— Wick

14

Chcesz dynamicznie budować wyrażenie regularne, a do tego poprawnym rozwiązaniem jest użycie new RegExp(string)konstruktora. Aby konstruktor mógł traktować znaki specjalne dosłownie , musisz uciec od nich. W widżecie autouzupełniania interfejsu jQuery jest wbudowana funkcja o nazwie $.ui.autocomplete.escapeRegex:

[...] możesz skorzystać z wbudowanej $.ui.autocomplete.escapeRegexfunkcji. Potrwa pojedynczy argument ciągu i uniknie wszystkich znaków wyrażenia regularnego, dzięki czemu wynik będzie bezpieczny do przekazania new RegExp().

Jeśli używasz interfejsu jQuery, możesz użyć tej funkcji lub skopiować jej definicję ze źródła :

function escapeRegex( value ) {
    return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
}

I użyj tego w ten sposób:

"[z-a][z-a][z-a]".replace(new RegExp(escapeRegex("[z-a]"), "g"), "[a-z]");
//            escapeRegex("[z-a]")       -> "\[z\-a\]"
// new RegExp(escapeRegex("[z-a]"), "g") -> /\[z\-a\]/g
// end result                            -> "[a-z][a-z][a-z]"

9
String.prototype.replaceAll = function (replaceThis, withThis) {
   var re = new RegExp(replaceThis,"g"); 
   return this.replace(re, withThis);
};
var aa = "abab54..aba".replaceAll("\\.", "v");

Przetestuj za pomocą tego narzędzia


5
String.prototype.replaceAll = function(a, b) {
    return this.replace(new RegExp(a.replace(/([.?*+^$[\]\\(){}|-])/ig, "\\$1"), 'ig'), b)
}

Przetestuj jak:

var whatever = 'Some [b]random[/b] text in a [b]sentence.[/b]'

console.log(whatever.replaceAll("[", "<").replaceAll("]", ">"))

4

Oto kolejna implementacja replaceAll:

    String.prototype.replaceAll = function (stringToFind, stringToReplace) {
        if ( stringToFind == stringToReplace) return this;
        var temp = this;
        var index = temp.indexOf(stringToFind);
        while (index != -1) {
            temp = temp.replace(stringToFind, stringToReplace);
            index = temp.indexOf(stringToFind);
        }
        return temp;
    };

4

I wersja odpowiedzi Stevena Penny'ego na coffeescript, ponieważ jest to wynik google nr 2 ... nawet jeśli kawa to tylko javascript z usuniętą dużą liczbą znaków ...;)

baz = "foo"
filter = new RegExp(baz + "d")
"food fight".match(filter)[0] // food

aw moim szczególnym przypadku

robot.name=hubot
filter = new RegExp(robot.name)
if msg.match.input.match(filter)
  console.log "True!"

dlaczego głosowanie negatywne? coffeescript -IS- javascript z własną specyficzną składnią.
— chętny

robot.name=hubotnie jest javascript.
— codepleb

3

Chociaż możesz tworzyć dynamicznie tworzone RegExp (zgodnie z innymi odpowiedziami na to pytanie), powtórzę mój komentarz z podobnego postu : Funkcjonalna forma String.replace () jest niezwykle przydatna i w wielu przypadkach zmniejsza potrzebę dynamicznie tworzone obiekty RegExp. (które są trochę uciążliwe, ponieważ musisz wyrazić dane wejściowe do konstruktora RegExp jako ciąg znaków zamiast używać formatu literalnego slash / [AZ] + / regexp)


3

Aby zaspokoić potrzebę wstawienia zmiennej / aliasu / funkcji do wyrażenia regularnego, oto co wymyśliłem:

oldre = /xx\(""\)/;
function newre(e){
    return RegExp(e.toString().replace(/\//g,"").replace(/xx/g, yy), "g")
};

String.prototype.replaceAll = this.replace(newre(oldre), "withThis");

gdzie „oldre” jest oryginalnym wyrażeniem regularnym, w którym chcę wstawić zmienną, „xx” jest symbolem zastępczym dla tej zmiennej / aliasu / funkcji, a „yy” jest rzeczywistą nazwą, aliasem lub funkcją zmiennej.


2

Możesz użyć tego, jeśli 1 USD nie działa z tobą

var pattern = new RegExp("amman","i");
"abc Amman efg".replace(pattern,"<b>"+"abc Amman efg".match(pattern)[0]+"</b>");

1

Zawsze możesz używać indexOfwielokrotnie:

String.prototype.replaceAll = function(substring, replacement) {
    var result = '';
    var lastIndex = 0;

    while(true) {
        var index = this.indexOf(substring, lastIndex);
        if(index === -1) break;
        result += this.substring(lastIndex, index) + replacement;
        lastIndex = index + substring.length;
    }

    return result + this.substring(lastIndex);
};

To nie przechodzi w nieskończoną pętlę, gdy zamiennik zawiera dopasowanie.


1

Twoje rozwiązanie jest tutaj:

Przekaż zmienną do wyrażenia regularnego.

Zaimplementowałem to, pobierając wartość z pola tekstowego, które chcesz zastąpić, a innym jest pole tekstowe „zamień na”, uzyskując wartość z pola tekstowego w zmiennej i ustawiając zmienną na RegExp funkcja do dalszej wymiany. W moim przypadku korzystam z Jquery, możesz to również zrobić tylko przez JavaScript.

Kod JavaScript:

  var replace =document.getElementById("replace}"); // getting a value from a text field with I want to replace
  var replace_with = document.getElementById("with"); //Getting the value from another text fields with which I want to replace another string.

  var sRegExInput = new RegExp(replace, "g");    
  $("body").children().each(function() {
    $(this).html($(this).html().replace(sRegExInput,replace_with));
  });

Ten kod znajduje się na zdarzeniu przycisku Onclick, możesz ustawić tę funkcję w celu wywołania.

Więc teraz możesz przekazać zmienną w funkcji zamień.


Twoja zmienna replace_with będzie zawierać element DOM, a nie samą wartość
— Ben Taliadoros

1

Ta funkcja wywołująca będzie iterować za pomocą replaceerItems za pomocą indeksu i zmieniać globalnie replaceerItems [indeks] w ciągu każdego przejścia.

  const replacerItems = ["a", "b", "c"];    

    function replacer(str, index){
          const item = replacerItems[index];
          const regex = new RegExp(`[${item}]`, "g");
          const newStr = str.replace(regex, "z");
          if (index < replacerItems.length - 1) {
            return replacer(newStr, index + 1);
          }
          return newStr;
    }

// console.log(replacer('abcdefg', 0)) will output 'zzzdefg'

0

Żadna z tych odpowiedzi nie była dla mnie jasna. W końcu znalazłem dobre wytłumaczenie na http://burnignorance.com/php-programming-tips/how-to-use-a-variable-in-replace-function-of-javascript/

Prosta odpowiedź brzmi:

var search_term = new RegExp(search_term, "g");    
text = text.replace(search_term, replace_term);

Na przykład:

$("button").click(function() {
  Find_and_replace("Lorem", "Chocolate");
  Find_and_replace("ipsum", "ice-cream");
});

function Find_and_replace(search_term, replace_term) {
  text = $("textbox").html();
  var search_term = new RegExp(search_term, "g");
  text = text.replace(search_term, replace_term);
  $("textbox").html(text);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textbox>
  Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum
</textbox>
<button>Click me</button>


1
Nadpisujesz zmienną zamknięcia, nie musisz jej vartutaj używać . Ponadto, jeśli zdasz \blub \1pęknie.
— CyberAP,

0

W przypadku wielokrotnego zastąpienia bez wyrażeń regularnych wybrałem następujące:

      let str = "I am a cat man. I like cats";
      let find = "cat";
      let replace = "dog";


      // Count how many occurrences there are of the string to find 
      // inside the str to be examined.
      let findCount = str.split(find).length - 1;

      let loopCount = 0;

      while (loopCount < findCount) 
      {
        str = str.replace(find, replace);
        loopCount = loopCount + 1;
      }  

      console.log(str);
      // I am a dog man. I like dogs

Tutaj znaleziono ważną część rozwiązania

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.