Comment utilisez-vous une variable dans une expression régulière?


1380

Je voudrais créer une String.replaceAll()méthode en JavaScript et je pense que l'utilisation d'une expression régulière serait la manière la plus laconique de le faire. Cependant, je ne peux pas comprendre comment passer une variable dans une expression régulière. Je peux déjà le faire, ce qui remplacera toutes les instances de "B"with "A".

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

Mais je veux faire quelque chose comme ça:

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

Mais évidemment, cela ne remplacera que le texte "replaceThis"... alors comment puis-je passer cette variable dans ma chaîne d'expression régulière?


9
Notez que nous travaillons actuellement sur l'ajout de cette fonctionnalité à JavaScript. Si vous avez une opinion à ce sujet, veuillez participer à la discussion.
Benjamin Gruenbaum

Réponses:


1842

Au lieu d'utiliser la /regex/gsyntaxe, vous pouvez construire un nouvel objet RegExp :

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

Vous pouvez créer dynamiquement des objets regex de cette façon. Ensuite, vous ferez:

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

272
Si vous avez besoin d'utiliser une expression comme /\/word\:\w*$/, assurez - vous d'échapper à vos antislashs: new RegExp( '\\/word\\:\\w*$' ).
Jonathan Swinney

2
@gravityboy Vous pouvez faire ('' + myNumber) .replace (/ 10 / g, 'a') ou si vous voulez des nombres hexadécimaux, vous pouvez faire parseInt ('' + myNumber, 16) pour convertir en hexadécimal à partir de la décimale.
Eric Wendelin

29
La question suggère que le RegEx n'est utilisé que pour effectuer un remplacement de chaîne constant. Donc, cette réponse est fausse car elle échouerait si la chaîne contient des méta caractères RegEx. Il est triste a voté ce haut, fera beaucoup de maux de tête ...
dronus

16
Un exemple de ce passage d'une variable en ferait une bonne réponse. J'ai encore du mal après avoir lu ça.
Goose

3
@JonathanSwinney: /n'a pas de signification particulière si vous construisez une expression régulière à partir d'une chaîne, vous n'avez donc pas besoin de l'échapper. /\/word\:\w*$/devrait êtrenew RegExp('/word\\:\\w*$')
Dávid Horváth

211

Comme Eric Wendelin l'a mentionné, vous pouvez faire quelque chose comme ceci:

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

Cela donne "regex matching .". Cependant, il échouera si str1 l'est ".". Vous vous attendriez à ce que le résultat soit "pattern matching regex", en remplaçant la période par "regex", mais il se révélera être ...

regexregexregexregexregexregexregexregexregexregexregexregexregexregexregexregexregexregex

Cela est dû au fait que, bien qu'il s'agisse d' "."une chaîne, dans le constructeur RegExp, il est toujours interprété comme une expression régulière, ce qui signifie tout caractère sans saut de ligne, ce qui signifie chaque caractère de la chaîne. À cet effet, la fonction suivante peut être utile:

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

Ensuite, vous pouvez faire:

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

céder "pattern matching regex".


4
Vous savez que le premier paramètre à remplacer peut être une chaîne normale et ne doit pas nécessairement être une expression rationnelle? str1 = "."; alert ("pattern matching.". replace (str1, "string"));
du

@some: bien sûr. C'est parce que l'exemple ci-dessus est trivial. Lorsque vous devez rechercher ou remplacer un modèle combiné avec une chaîne régulière, faites str.match (new RegExp ("https?: //" + RegExp.escape (myDomainName)), par exemple. Il est ennuyeux que la fonction d'échappement soit pas construit.
Gracenotes

(suite) De plus, JC Grubbs avait apparemment besoin d'un remplacement mondial; l'implémentation d'un remplacement global par String.replace (String, String) peut être lente pour une entrée volumineuse. Je dis juste, les deux premières solutions sont boguées et échoueront inattendues sur certaines entrées.
Gracenotes du

4
developer.mozilla.org/en-US/docs/JavaScript/Guide/… offre une fonction similaire, mais ils excluent -et incluent =!:/.
chbrown

8
Le terme correct est "évasion", pas "citation". Juste BTW.
Lawrence Dol

118

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

Comme toujours: n'utilisez pas l'expression régulière sauf si vous le devez. Pour un simple remplacement de chaîne, l'idiome est:

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

Ensuite, vous n'avez pas à vous soucier des problèmes de citation mentionnés dans la réponse de Gracenotes.


11
Et avez-vous mesuré que c'est plus rapide que l'expression régulière?
Mitar

3
Cela semble préférable, en particulier lorsque vous devez faire correspondre des caractères d'expressions spéciales comme '.'
Krease

1
Uhm ... Ne divise pas aussi prendre un RegExp; si oui, ne causerait-il pas le même problème? Quoi qu'il en soit ... .split (). Join () peut être plus lent sur certaines plates-formes, car il s'agit de deux opérations, tandis que .replace () est une opération et peut être optimisé.

5
@ PacMan--: les deux splitet replacepeuvent prendre une chaîne ou un RegExpobjet. Le problème que replacecela splitne pose pas est que lorsque vous utilisez une chaîne, vous n'obtenez qu'un seul remplacement.
bobince


38

Si vous voulez obtenir TOUTES les occurrences ( g), soyez insensible à la casse ( i) et utilisez des limites pour que ce ne soit pas un mot dans un autre mot ( \\b):

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

Exemple:

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.

Merci! (afaict, la vôtre est la seule réponse explicite avec rxune interpolation Emacs / -style, via des chaînes de modèle.)
sam boosalis

34

Pour tous ceux qui cherchent à utiliser une variable avec la méthode de correspondance , cela a fonctionné pour moi

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


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

J'aime cette réponse car elle ne crée pas la variable supplémentaire (& inutile).
Wick

14

Vous voulez construire l'expression régulière dynamiquement et pour cela, la bonne solution est d'utiliser le new RegExp(string)constructeur. Pour que le constructeur traite les caractères spéciaux littéralement , vous devez leur échapper. Il y a une fonction intégrée dans le widget de saisie semi-automatique jQuery UI appelée $.ui.autocomplete.escapeRegex:

[...] vous pouvez utiliser la $.ui.autocomplete.escapeRegexfonction intégrée. Cela prendra un seul argument de chaîne et échappera à tous les caractères regex, ce qui rend le résultat sûr à passer new RegExp().

Si vous utilisez jQuery UI, vous pouvez utiliser cette fonction ou copier sa définition à partir de la source :

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

Et utilisez-le comme ceci:

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

Testez avec cet outil


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

Testez-le comme:

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

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

4

Voici une autre implémentation 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

Et la version coffeescript de la réponse de Steven Penny, puisque c'est le résultat n ° 2 de Google .... même si le café est juste javascript avec beaucoup de caractères supprimés ...;)

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

et dans mon cas particulier

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

pourquoi un downvote? coffeescript -IS- javascript avec sa propre syntaxe spécifique.
vif

robot.name=hubotn'est pas javascript.
codepleb

3

Bien que vous puissiez créer des RegExp créés dynamiquement (selon les autres réponses à cette question), je ferai écho à mon commentaire d'un article similaire : La forme fonctionnelle de String.replace () est extrêmement utile et dans de nombreux cas, réduit le besoin de objets RegExp créés dynamiquement. (qui sont un peu pénibles, car vous devez exprimer l'entrée du constructeur RegExp sous forme de chaîne plutôt que d'utiliser le format littéral slash / [AZ] + / regexp)


3

Pour satisfaire mon besoin d'insérer une variable / alias / fonction dans une expression régulière, voici ce que j'ai trouvé:

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

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

où 'oldre' est l'expression rationnelle d'origine que je veux insérer une variable, 'xx' est l'espace réservé pour cette variable / alias / fonction, et 'yy' est le nom de variable, l'alias ou la fonction réelle.


2

Vous pouvez l'utiliser si $ 1 ne fonctionne pas avec vous

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

1

Vous pouvez toujours utiliser à indexOfplusieurs reprises:

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

Cela ne va pas dans une boucle infinie lorsque le remplacement contient la correspondance.


1

Votre solution est ici:

Passez une variable à une expression régulière.

Celui que j'ai mis en œuvre consiste à prendre la valeur d'un champ de texte qui est celui que vous souhaitez remplacer et un autre est le champ de texte "remplacer par", en obtenant la valeur du champ de texte dans une variable et en définissant la variable sur RegExp fonction à remplacer. Dans mon cas, j'utilise Jquery, vous pouvez également le faire uniquement avec JavaScript.

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

Ce code est sur événement Onclick d'un bouton, vous pouvez le mettre dans une fonction à appeler.

Alors maintenant, vous pouvez passer une variable dans la fonction de remplacement.


Votre variable replace_with contiendra l'élément DOM et non la valeur elle
Ben Taliadoros

1

Cette fonction auto-appelée itérera sur replacerItems à l'aide d'un index et changera globalement replacerItems [index] sur la chaîne à chaque passage.

  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

Aucune de ces réponses n'était claire pour moi. J'ai finalement trouvé une bonne explication sur http://burnignorance.com/php-programming-tips/how-to-use-a-variable-in-replace-function-of-javascript/

La réponse simple est:

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

Par exemple:

$("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
Vous écrasez une variable de fermeture, inutile de l'utiliser varici. De plus, si vous passez \bou \1cela casserait.
CyberAP

0

Pour plusieurs remplacements sans expressions régulières, je suis allé avec ce qui suit:

      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

La partie importante de la solution a été trouvée ici

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.