¿Cómo se usa una variable en una expresión regular?

1609

Me gustaría crear un String.replaceAll()método en JavaScript y estoy pensando que usar una expresión regular sería la forma más concisa de hacerlo. Sin embargo, no puedo averiguar cómo pasar una variable a una expresión regular. Ya puedo hacer esto, lo que reemplazará todas las instancias de "B"con "A".

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

Pero quiero hacer algo como esto:

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

Pero obviamente esto solo reemplazará el texto "replaceThis"... entonces, ¿cómo paso esta variable a mi cadena de expresiones regulares?

1
2128

En lugar de usar la /regex\d/gsintaxis, puede construir un nuevo objeto RegExp :

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

Puede crear dinámicamente objetos regex de esta manera. Entonces harás:

"mystring1".replace(re, "newstring");
20
  • 307
    Si es necesario utilizar una expresión como /\/word\:\w*$/, asegúrese de escapar de sus barras invertidas: new RegExp( '\\/word\\:\\w*$' ). Jonathan Swinney 9/11/10 a las 23:04
  • 2
    @gravityboy Puede hacer ('' + myNumber) .replace (/ 10 / g, 'a') o si desea números hexadecimales, puede hacer parseInt ('' + myNumber, 16) para convertir a hexadecimal de decimal. Eric Wendelin 21/06/11 a las 15:19
  • 45
    La pregunta sugiere que la expresión regular solo se usa para hacer un reemplazo de cadena constante. Entonces, esta respuesta es incorrecta, ya que fallaría si la cadena contiene metacaracteres RegEx. Triste, es votado tan alto, causará muchos dolores de cabeza ...dronus 12 feb 2014 a las 20:32
  • 26
    Un ejemplo de esto pasar una variable haría que esta sea una buena respuesta. Todavía estoy luchando después de leer esto. Goose 5/06/2015 a las 18:44
  • 3
    @JonathanSwinney: /no tiene un significado especial si construye expresiones regulares a partir de una cadena, por lo que no necesita escapar de ella. /\/word\:\w*$/debería sernew RegExp('/word\\:\\w*$')Dávid Horváth 11 de enero de 2017 a las 13:52
238

Como mencionó Eric Wendelin, puede hacer algo como esto:

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

Esto cede "regex matching .". Sin embargo, fallará si str1 es ".". Es de esperar que el resultado sea "pattern matching regex", reemplazando el punto con "regex", pero resultará ser ...

regexregexregexregexregexregexregexregexregexregexregexregexregexregexregexregexregexregex

Esto se debe a que, aunque "."es una cadena, en el constructor RegExp todavía se interpreta como una expresión regular, es decir, cualquier carácter sin salto de línea, es decir, todos los caracteres de la cadena. Para ello, puede resultar útil la siguiente función:

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

Entonces puedes hacer:

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

ceder "pattern matching regex".

10
  • 4
    ¿Sabe que el primer parámetro a reemplazar puede ser una cadena normal y no tiene que ser una expresión regular? str1 = "."; alert ("coincidencia de patrones.". replace (str1, "string")); some 30 de ene. De 2009 a las 10:31
  • @algunos: por supuesto. Eso es porque el ejemplo anterior es trivial. Cuando necesite buscar o reemplazar un patrón combinado con una cadena regular, haga str.match (new RegExp ("https?: //" + RegExp.escape (myDomainName)), por ejemplo. Es molesto que la función de escape sea no incorporado.Gracenotes 30 de ene. De 2009 a las 19:57
  • (continuación) Además, aparentemente, JC Grubbs necesitaba un reemplazo global; implementar un reemplazo global con String.replace (String, String) podría ser lento para una entrada grande. Solo digo que las dos soluciones principales tienen errores y fallarán inesperadamente en cierta entrada. Gracenotes 30 de ene. De 2009 a las 20:00
  • 5
    developer.mozilla.org/en-US/docs/JavaScript/Guide/… ofrece una función similar, pero excluye -e incluye =!:/. chbrown 15/12/12 a las 21:12
  • 8
    El término correcto es "escape", no "cita". Solo por cierto. Lawrence Dol 4 de diciembre de 2015 a las 5:19
128

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

Como siempre: no use expresiones regulares a menos que sea necesario. Para un reemplazo de cadena simple, el modismo es:

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

Entonces no tiene que preocuparse por los problemas de citas mencionados en la respuesta de Gracenotes.

9
  • 13
    ¿Y ha medido que esto es más rápido que la expresión regular? Mitar 10 de abril de 2013 a las 3:12
  • 3
    Esto parece preferible, especialmente cuando se necesita hacer coincidir caracteres especiales de expresiones regulares como '.' Krease 24/04/13 a las 18:41
  • 1
    Uhm ... No toma una expresión regular también; si es así, ¿no causaría el mismo problema? De todos modos ... .split (). Join () puede ser más lento en algunas plataformas, porque son dos operaciones, mientras que .replace () es una operación y puede estar optimizado. user1985657 12/06/2013 a las 22:47
  • 5
    @ PacMan--: ambos splity replacepueden tomar una cuerda o un RegExpobjeto. El problema que replacetiene eso splites que cuando usas una cadena solo obtienes un reemplazo. bobince 13 de junio de 2013 a las 9:05
  • 2
    punto de referencia aquí: jsperf.com/replace-vs-split-join-vs-replaceall/23Wagner Danda da Silva Filho 21 feb 2018 a las 16:42
64

Si desea obtener todas las apariciones ( g), no distinga entre mayúsculas y minúsculas ( i) y use límites para que no sea una palabra dentro de otra palabra ( \\b):

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

Ejemplo:

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.
1
  • 1
    ¡gracias! (Afaict, la suya es la única respuesta explícitamente con rxinterpolación de estilo Emacs / , a través de cadenas de plantilla)sam boosalis 8 abr.20 a las 3:30
36

Para cualquiera que busque usar una variable con el método de coincidencia , esto funcionó para mí:

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

Esta:

var txt=new RegExp(pattern,attributes);

es equivalente a esto:

var txt=/pattern/attributes;

Consulte http://www.w3schools.com/jsref/jsref_obj_regexp.asp .

1
  • 24
    sí, pero en el primer ejemplo se usa patterncomo variable, en el segundo como una cadenavladkras 9 de julio de 2013 a las 4:16
30
this.replace( new RegExp( replaceThis, 'g' ), withThis );
1
  • Me gusta esta respuesta ya que no crea la variable adicional (y sin sentido). Wick 4/04/19 a las 15:20
16

Desea construir la expresión regular de forma dinámica y, para ello, la solución adecuada es utilizar el new RegExp(string)constructor. Para que el constructor trate los caracteres especiales literalmente , debe escapar de ellos. Hay una función incorporada en el widget de autocompletar de jQuery UI llamado $.ui.autocomplete.escapeRegex:

[...] you can make use of the built-in $.ui.autocomplete.escapeRegex function. It'll take a single string argument and escape all regex characters, making the result safe to pass to new RegExp().

Si está usando jQuery UI , puede usar esa función o copiar su definición de la fuente :

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

Y utilícelo así:

"[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]"
10
String.prototype.replaceAll = function (replaceThis, withThis) {
   var re = new RegExp(replaceThis,"g"); 
   return this.replace(re, withThis);
};
var aa = "abab54..aba".replaceAll("\\.", "v");

Prueba con esta herramienta

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

Pruébelo como:

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

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

Para satisfacer mi necesidad de insertar una variable / alias / función en una expresión regular, esto es lo que se me ocurrió:

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

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

donde 'oldre' es la expresión regular original en la que quiero insertar una variable, 'xx' es el marcador de posición para esa variable / alias / función, y 'yy' es el nombre, alias o función de la variable real.

1
  • Después de probar todas y cada una de las soluciones para insertar una variable dentro de la expresión regular, la suya fue la única que funcionó para mí. ¡Muchas gracias! RoberRM 26/06/20 a las 1:23
5

Puede utilizar una cadena como expresión regular. No olvide utilizar la nueva expresión regular .

Ejemplo:

var yourFunction = new RegExp(
        '^-?\\d+(?:\\.\\d{0,' + yourVar + '})?'
      )
5

Y la versión CoffeeScript de la respuesta de Steven Penny , ya que este es el resultado número 2 de Google ... incluso si CoffeeScript es solo JavaScript con muchos caracteres eliminados ...;)

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

Y en mi caso particular:

robot.name = hubot
filter = new RegExp(robot.name)
if msg.match.input.match(filter)
  console.log "True!"
2
  • ¿Por qué un voto negativo? coffeescript -IS- javascript con su propia sintaxis específica. keen 26/08/15 a las 15:53
  • 3
    robot.name=hubotno es javascript. codepleb 31/01/20 a las 14:14
4

Aquí hay otra implementación de 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;
    };
3

Si bien puede hacer RegExp creadas dinámicamente (según las otras respuestas a esta pregunta), me haré eco de mi comentario de una publicación similar : la forma funcional de String.replace () es extremadamente útil y en muchos casos reduce la necesidad de Objetos RegExp creados dinámicamente. (que son un poco molestos porque tienes que expresar la entrada al constructor RegExp como una cadena en lugar de usar el formato literal de barras inclinadas / [AZ] + / regexp)

3

Esta función de auto-llamada iterará sobre replacerItems usando un índice, y cambiará replacerItems [index] globalmente en la cadena con cada pasada.

  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'
3

Puede usar esto si $1no funciona para usted:

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

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

Esto no entra en un ciclo infinito cuando el reemplazo contiene la coincidencia.

1

Ninguna de estas respuestas me resultó clara. Finalmente encontré una buena explicación en Cómo usar una variable en la función de reemplazo de JavaScript

La respuesta simple es:

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

Por ejemplo:

$("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
  • 1
    Está sobrescribiendo una variable de cierre, no es necesario usarla varaquí. Además, si pasa \bo \1se rompería. CyberAP 6 nov 2018 a las 19:00
1

Tu solución está aquí:

Pasar una variable a una expresión regular

El que he implementado es tomando el valor de un campo de texto que es el que desea reemplazar y otro es el campo de texto "reemplazar con", obteniendo el valor del campo de texto en una variable y estableciendo la variable en RegExp función para reemplazar aún más. En mi caso, estoy usando jQuery, pero también puedes hacerlo solo con 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á en el evento Onclick de un botón y puede ponerlo en una función para llamar.

Entonces ahora puede pasar una variable en la función de reemplazo.

3
  • Su variable replace_with contendrá el elemento DOM, no el valor en síBen Taliadoros 27 oct 2017 a las 14:26
  • El enlace está roto: "Página no encontrada - Mindfire Solutions. 404. Parece que estás perdido". Peter Mortensen 22 de agosto a las 11:54
  • Simplemente ignore el enlace, puede usar el código dado en la respuesta, debería funcionar en consecuenciaAjit Hogade 24 de agosto a las 11:42
0

Para reemplazo múltiple sin expresiones regulares, elegí lo siguiente:

      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 parte importante de la solución se encontró aquí.

0

Si pasa la variable con la sintaxis correcta, puede hacerlo así con el siguiente código.

Esto tiene el beneficio adicional de usar las banderas en la misma variable.

Además, no tiene que hacer doble escape \en la expresión regular cuando se trata de \w, etc.

var str = 'regexVariable example: This is my example of RegExp replacing with a regexVariable.'
var reVar = /(.*?)(regex\w+?iable)(.+?)/gi;
var resStr = str.replace(new RegExp(reVar), '$1 :) :) :) $2 :) :) :)$3');
console.log(resStr);

// Returns:
// :) :) :) regexVariable :) :) :) example: This is my example of RegExp replacing with a  :) :) :) regexVariable :) :) :).

La versión prototipo según el ejemplo del OP:

var str = 'regexVariable prototype: This is my example of RegExp replacing with a regexVariable.'

String.prototype.regexVariable = function(reFind, reReplace) {
return str.replace(new RegExp(reFind), reReplace);
}

var reVar = /(.*?)(regex\w+?iable)(.+?)/gi;

console.log(str.regexVariable(reVar, '$1 :) :) :) $2 :) :) :)$3'));

// Returns:
// :) :) :) regexVariable :) :) :) prototype: This is my example of replacing with a  :) :) :) regexVariable :) :) :).
0

Como un novato relativo de JavaScript, la respuesta aceptada https://stackoverflow.com/a/494046/1904943 se nota / aprecia, pero no es muy intuitiva.

Aquí hay una interpretación más simple, por ejemplo (usando un IDE de JavaScript simple ).

myString = 'apple pie, banana loaf';

console.log(myString.replaceAll(/pie/gi, 'PIE'))
// apple PIE, banana loaf

console.log(myString.replaceAll(/\bpie\b/gi, 'PIE'))
// apple PIE, banana loaf

console.log(myString.replaceAll(/pi/gi, 'PIE'))
// apple PIEe, banana loaf

console.log(myString.replaceAll(/\bpi\b/gi, 'PIE'))
// [NO EFFECT] apple pie, banana loaf

const match_word = 'pie';

console.log(myString.replaceAll(/match_word/gi, '**PIE**'))
// [NO EFFECT] apple pie, banana loaf

console.log(myString.replaceAll(/\b`${bmatch_word}`\b/gi, '**PIE**'))
// [NO EFFECT] apple pie, banana loaf

// ----------------------------------------
// ... new RegExp(): be sure to \-escape your backslashes: \b >> \\b ...

const match_term = 'pie';
const match_re = new RegExp(`(\\b${match_term}\\b)`, 'gi')

console.log(myString.replaceAll(match_re, 'PiE'))
// apple PiE, banana loaf

console.log(myString.replace(match_re, '**PIE**'))
// apple **PIE**, banana loaf

console.log(myString.replaceAll(match_re, '**PIE**'))
// apple **PIE**, banana loaf

Solicitud

Por ejemplo: reemplazar (resaltar con color) palabras en una cadena / oración, [opcionalmente] si el término de búsqueda coincide con una proporción de la palabra coincidente mayor que la definida por el usuario.

Nota: se retiene el caso del carácter original del término coincidente. hl: destacar; re: regex | expresión regular

mySentence = "Apple, boOk? BOoks; booKEd. BookMark, 'BookmarkeD', bOOkmarks! bookmakinG, Banana; bE, BeEn, beFore."

function replacer(mySentence, hl_term, hl_re) {
    console.log('mySentence [raw]:', mySentence)
    console.log('hl_term:', hl_term, '| hl_term.length:', hl_term.length)
    cutoff = hl_term.length;
    console.log('cutoff:', cutoff)

    // `.match()` conveniently collects multiple matched items
    // (including partial matches) into an [array]
    const hl_terms  = mySentence.toLowerCase().match(hl_re, hl_term);
    if (hl_terms == null) {
        console.log('No matches to hl_term "' + hl_term + '"; echoing input string then exiting ...')
        return mySentence;
    }
    console.log('hl_terms:', hl_terms)
    for (let i = 0;  i < hl_terms.length; i++) {
        console.log('----------------------------------------')
        console.log('[' + i + ']:', hl_terms[i], '| length:', hl_terms[i].length, '| parseInt(0.7(length)):', parseInt(0.7*hl_terms[i].length))
        // TEST: if (hl_terms[i].length >= cutoff*10) {
        if (cutoff >= parseInt(0.7 * hl_terms[i].length)) {
            var match_term = hl_terms[i].toString();

            console.log('matched term:', match_term, '[cutoff length:', cutoff, '| 0.7(matched term length):', parseInt(0.7 * hl_terms[i].length))

            const match_re = new RegExp(`(\\b${match_term}\\b)`, 'gi')

            mySentence = mySentence.replaceAll(match_re, '<font style="background:#ffe74e">$1</font>');
        }
        else {
            var match_term = hl_terms[i].toString();
            console.log('NO match:', match_term, '[cutoff length:', cutoff, '| 0.7(matched term length):', parseInt(0.7 * hl_terms[i].length))
        }
    }
    return mySentence;
}

// TESTS:
// const hl_term = 'be';
// const hl_term = 'bee';
// const hl_term = 'before';
// const hl_term = 'book';
const hl_term = 'bookma';
// const hl_term = 'Leibniz';

// This regex matches from start of word:
const hl_re = new RegExp(`(\\b${hl_term}[A-z]*)\\b`, 'gi')

mySentence = replacer(mySentence, hl_term, hl_re);
console.log('mySentence [processed]:', mySentence)

Producción

mySentence [raw]: Apple, boOk? BOoks; booKEd. BookMark, 'BookmarkeD',
bOOkmarks! bookmakinG, Banana; bE, BeEn, beFore.

hl_term: bookma | hl_term.length: 6
cutoff: 6
hl_terms: Array(4) [ "bookmark", "bookmarked", "bookmarks", "bookmaking" ]

----------------------------------------
[0]: bookmark | length: 8 | parseInt(0.7(length)): 5
matched term: bookmark [cutoff length: 6 | 0.7(matched term length): 5
----------------------------------------
[1]: bookmarked | length: 10 | parseInt(0.7(length)): 7
NO match: bookmarked [cutoff length: 6 | 0.7(matched term length): 7
----------------------------------------
[2]: bookmarks | length: 9 | parseInt(0.7(length)): 6
matched term: bookmarks [cutoff length: 6 | 0.7(matched term length): 6
----------------------------------------
[3]: bookmaking | length: 10 | parseInt(0.7(length)): 7
NO match: bookmaking [cutoff length: 6 | 0.7(matched term length): 7

mySentence [processed]: Apple, boOk? BOoks; booKEd.
<font style="background:#ffe74e">BookMark</font>, 'BookmarkeD',
<font style="background:#ffe74e">bOOkmarks</font>! bookmakinG,
Banana; bE, BeEn, beFore.