Como você usa uma variável em uma expressão regular?


1380

Gostaria de criar um String.replaceAll()método em JavaScript e estou pensando que usar um regex seria a maneira mais concisa de fazê-lo. No entanto, não consigo descobrir como passar uma variável para uma regex. Eu posso fazer isso já que irá substituir todas as instâncias de "B"com "A".

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

Mas eu quero fazer algo assim:

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

Mas, obviamente, isso substituirá apenas o texto "replaceThis"... então, como passo essa variável para minha string regex?


9
No momento, estamos trabalhando para adicionar essa funcionalidade ao JavaScript, se você tiver uma opinião sobre isso, por favor, participe da discussão.
— Benjamin Gruenbaum

Respostas:


1842

Em vez de usar a /regex/gsintaxe, você pode construir um novo objeto RegExp :

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

Você pode criar dinamicamente objetos regex dessa maneira. Então você fará:

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

272
Se você precisar usar uma expressão como /\/word\:\w*$/ , certifique-se de escapar de seus barras invertidas: new RegExp( '\\/word\\:\\w*$' ).
— Jonathan Swinney

2
@gravityboy Você pode fazer ('' + meuNúmero). substituir (/ 10 / g, 'a') ou, se quiser números hexadecimais, pode fazer parseInt ('' + meuNúmero, 16) para converter para hexadecimal de decimal.
— Eric Wendelin

29
A pergunta sugere que o RegEx é usado apenas para fazer uma substituição de seqüência constante. Portanto, esta resposta está errada, pois falharia se a sequência contivesse meta caracteres RegEx. Triste que seja votado tão alto, fará muitas dores de cabeça ...
— dronus

16
Um exemplo dessa passagem de uma variável tornaria essa uma boa resposta. Eu ainda estou lutando depois de ler isso.
— Ganso

3
@ JonathanSwinney: /não tem significado especial se você construir regex a partir de uma string, para que você não precise escapar dela. /\/word\:\w*$/deveria sernew RegExp('/word\\:\\w*$')
— Dávid Horváth

211

Como Eric Wendelin mencionou, você pode fazer algo assim:

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

Isso gera "regex matching ." . No entanto, ele falhará se str1 for ".". Você esperaria que o resultado fosse "pattern matching regex", substituindo o período por "regex", mas acabará sendo ...

regexregexregexregexregexregexregexregexregexregexregexregexregexregexregexregexregexregex

Isso ocorre porque, embora "."seja uma String, no construtor RegExp ainda é interpretado como uma expressão regular, significando qualquer caractere que não seja de quebra de linha, ou seja, todos os caracteres da string. Para esse fim, a seguinte função pode ser útil:

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

Então você pode fazer:

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

cedendo "pattern matching regex".


4
Você sabe que o primeiro parâmetro a substituir pode ser uma sequência normal e não precisa ser uma regexp? str1 = "."; alert ("correspondência de padrões.". replace (str1, "string"));
— algum dia

@ alguns: é claro. Isso ocorre porque o exemplo acima é trivial. Quando você precisar procurar ou substituir um padrão combinado com uma sequência regular, execute str.match (new RegExp ("https?: //" + RegExp.escape (myDomainName))), por exemplo. É irritante que a função de escape seja não construído em.
— Gracenotes

(continuação) Além disso, o aparente JC Grubbs exigiu uma substituição global; implementar uma substituição global por String.replace (String, String) pode ser lento para entradas grandes. Só estou dizendo que as duas principais soluções são incorretas e falharão inesperadamente em determinadas entradas.
— Gracenotes

4
developer.mozilla.org/pt-BR/docs/JavaScript/Guide/… oferece uma função semelhante, mas eles excluem -e incluem =!:/.
— chbrown

8
O termo correto é "escape", não "quote". Apenas entre.
— Lawrence Dol

118

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

Como sempre: não use regex a menos que você precise. Para uma substituição simples de cadeia, o idioma é:

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

Então você não precisa se preocupar com os problemas de citação mencionados na resposta do Gracenotes.


11
E você mediu que isso é mais rápido que o regex?
— quer

3
Isso parece preferível, especialmente quando é necessário combinar caracteres regex especiais como '.'
— Krease

1
Uhm ... Também não é necessário dividir um RegExp; Nesse caso, não causaria o mesmo problema? De qualquer forma ... .split (). Join () pode ser mais lento em algumas plataformas, porque são duas operações, enquanto .replace () é uma operação e pode ser otimizado.

5
@ PacMan--: ambos splite replacepodem pegar uma string ou um RegExpobjeto. O problema que replacetem isso splitnão é que, quando você usa uma string, obtém apenas uma única substituição.
— bobince


38

Se você deseja obter TODAS as ocorrências ( g), faça distinção entre maiúsculas e minúsculas ( i) e use limites para que não seja uma palavra dentro de outra palavra ( \\b):

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

Exemplo:

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.

obrigado! (Afinal, a sua é a única resposta explicitamente com a rxinterpolação Emacs / style, por meio de strings de modelo.)
— sam boosalis

34

Para quem procura usar variável com o método match , isso funcionou para mim

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


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

Gosto dessa resposta, pois ela não cria a variável extra (e sem sentido).
— Wick

14

Você deseja construir a expressão regular dinamicamente e, para isso, a solução adequada é usar o new RegExp(string)construtor. Para que o construtor trate caracteres especiais literalmente , você deve escapar deles. Há uma função interna no widget de preenchimento automático da UI do jQuery chamada $.ui.autocomplete.escapeRegex:

[...] você pode fazer uso da $.ui.autocomplete.escapeRegexfunção embutida. Será necessário um único argumento de string e escapará a todos os caracteres regex, tornando o resultado seguro para passar new RegExp().

Se você estiver usando a interface do usuário do jQuery, poderá usar essa função ou copiar sua definição da fonte :

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

E use-o assim:

"[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");

Teste com esta ferramenta


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

Teste como:

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

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

4

Aqui está outra implementação 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

E a versão coffeescript da resposta de Steven Penny, já que este é o resultado # 2 do google .... mesmo que o café seja apenas javascript com muitos caracteres removidos ...;)

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

e no meu caso particular

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

por que um voto negativo? coffeescript -IS- javascript com sua própria sintaxe específica.
— afiado

robot.name=hubotnão é javascript.
— codepleb 31/01

3

Embora você possa criar RegExp criados dinamicamente (conforme as outras respostas a esta pergunta), repetirei meu comentário em um post semelhante : A forma funcional de String.replace () é extremamente útil e, em muitos casos, reduz a necessidade de objetos RegExp criados dinamicamente. (que é meio doloroso porque você precisa expressar a entrada para o construtor RegExp como uma sequência de caracteres, em vez de usar o formato literal de barras / [AZ] + / regexp)


3

Para satisfazer minha necessidade de inserir uma variável / alias / function em uma Expressão Regular, é isso que eu criei:

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

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

onde 'oldre' é o regexp original que eu quero inserir uma variável, 'xx' é o espaço reservado para essa variável / alias / function e 'yy' é o nome, o alias ou a função real da variável.


2

Você pode usar isso se $ 1 não funcionar com você

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

1

Você sempre pode usar indexOfrepetidamente:

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);
};

Isso não entra em um loop infinito quando a substituição contém a correspondência.


1

Sua solução está aqui:

Passe uma variável para expressão regular.

O que eu implementei é pegar o valor de um campo de texto que você deseja substituir e outro é o campo de texto "substituir por", obtendo o valor do campo de texto em uma variável e definindo a variável como RegExp função para substituir ainda mais. No meu caso, estou usando o Jquery, você também pode fazê-lo apenas com JavaScript.

Código 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));
  });

Este código está no evento Onclick de um botão, você pode colocar isso em uma função para chamar.

Então agora você pode passar variáveis ​​na função de substituição.


Sua variável substituir_por conterá o elemento DOM não o valor em si
— Ben Taliadoros

1

Essa função de auto-chamada itera sobre o substiterItems usando um índice e altera o substituerItems [index] globalmente na cadeia a cada passagem.

  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

Nenhuma dessas respostas estava clara para mim. Acabei encontrando uma boa explicação em http://burnignorance.com/php-programming-tips/how-to-use-a-variable-in-replace-function-of-javascript/

A resposta simples é:

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

Por exemplo:

$("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
Você está substituindo uma variável de fechamento, não precisa usar varaqui. Além disso, se você passar \bou \1ele iria quebrar.
— CyberAP

0

Para substituição múltipla sem expressões regulares, fui com o seguinte:

      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

A parte importante da solução foi encontrada aqui

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.