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

1380

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 entender cómo pasar una variable a una expresión regular. Ya puedo hacer esto, 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?

JC Grubbs
fuente
99
Tenga en cuenta que actualmente estamos trabajando para agregar esta funcionalidad a JavaScript si tiene una opinión al respecto, únase a la discusión.
Benjamin Gruenbaum

Respuestas:

1842

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

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

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

"mystring".replace(re, "newstring");
Eric Wendelin
fuente
272
Si es necesario utilizar una expresión como /\/word\:\w*$/, asegúrese de escapar de sus barras invertidas: new RegExp( '\\/word\\:\\w*$' ).
Jonathan Swinney el
2
@gravityboy Puede hacer ('' + myNumber) .replace (/ 10 / g, 'a') o si desea números hexadecimales, puede hacer parseInt ('' + myNumber, 16) para convertir a hexadecimal desde decimal.
Eric Wendelin
29
La pregunta sugiere que el RegEx 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. Es triste que se haya votado tan alto, hará muchos dolores de cabeza ...
Dronus
16
Un ejemplo de esto pasando una variable haría que esta sea una buena respuesta. Todavía estoy luchando después de leer esto.
Goose
3
@JonathanSwinney: /no tiene un significado especial si construye regex a partir de una cadena, por lo que no necesita escapar de él. /\/word\:\w*$/debería sernew RegExp('/word\\:\\w*$')
Dávid Horváth
211

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

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

Esto rinde "regex matching .". Sin embargo, fallará si str1 es ".". Es de esperar que el resultado sea "pattern matching regex", reemplazando el período 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 este propósito, la siguiente función puede ser útil:

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

cediendo "pattern matching regex".

Gracenotes
fuente
44
¿Sabes que el primer parámetro para reemplazar puede ser una cadena normal y no tiene que ser una expresión regular? str1 = "."; alert ("coincidencia de patrones". replace (str1, "string"));
Algunos
@some: 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 (nuevo RegExp ("https?: //" + RegExp.escape (myDomainName)), por ejemplo. Es molesto que la función de escape sea no incorporado.
Gracenotes
(continuación) Además, aparentemente JC Grubbs requirió un reemplazo global; implementar un reemplazo global con String.replace (String, String) podría ser lento para entradas grandes. Solo digo que las dos soluciones principales tienen errores y fallarán inesperadamente en ciertas entradas.
Gracenotes
44
developer.mozilla.org/en-US/docs/JavaScript/Guide/… ofrece una función similar, pero excluyen -e incluyen =!:/.
chbrown
8
El término correcto es "escapar", no "citar". Solo por cierto.
Lawrence Dol
118

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

Como siempre: no use expresiones regulares a menos que sea necesario. Para reemplazar una cadena simple, el idioma es:

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

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

bobince
fuente
11
¿Y has medido que esto es más rápido que regex?
Mitar
3
Esto parece preferible, especialmente cuando se necesita hacer coincidir caracteres especiales de expresiones regulares como ''.
Krease
1
Uhm ... No se divide, toma un RegExp 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 optimizarse.
55
@ PacMan--: ambos splity replacepueden tomar una cadena o un RegExpobjeto. El problema que replacetiene eso splitno es que cuando usas una cadena solo obtienes un solo reemplazo.
bobince
1
punto de referencia aquí: jsperf.com/replace-vs-split-join-vs-replaceall/23
Wagner da Silva
38

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.
JBallin
fuente
¡gracias! (De hecho, la suya es la única respuesta explícita con la rxinterpolación Emacs / -style, a través de cadenas de plantillas).
Sam Boosalis
34

Para cualquiera que quiera usar variables con el método de coincidencia , esto funcionó para mí

var alpha = 'fig';
'food fight'.match(alpha + 'ht')[0]; // fight
Steven Penny
fuente
20
this.replace( new RegExp( replaceThis, 'g' ), withThis );
tvanfosson
fuente
Me gusta esta respuesta, ya que no crea la variable adicional (y sin sentido).
Wick
14

Desea construir la expresión regular dinámicamente y para esto la solución adecuada es usar el new RegExp(string)constructor. Para que el constructor trate caracteres especiales literalmente , debe escapar de ellos. Hay una función incorporada en el widget de autocompletado de jQuery UI llamada $.ui.autocomplete.escapeRegex:

[...] puede hacer uso de la $.ui.autocomplete.escapeRegexfunción incorporada. Tomará un solo argumento de cadena y escapará de todos los caracteres regex, haciendo que el resultado sea seguro para pasar new RegExp().

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

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

Y úsalo 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]"
Salman A
fuente
9
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

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

Pruébalo como:

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

console.log(whatever.replaceAll("[", "<").replaceAll("]", ">"))
MetalGodwin
fuente
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;
    };
scripto
fuente
4

Y la versión coffeescript de la respuesta de Steven Penny, ya que este es el resultado # 2 de Google ... incluso si el café 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!"
afilado
fuente
¿Por qué un voto negativo? coffeescript -IS- javascript con su propia sintaxis específica.
entusiasta
robot.name=hubotno es javascript
codepleb
3

Si bien puede crear RegExp creados dinámicamente (según las otras respuestas a esta pregunta), haré eco de mi comentario en 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. (lo cual es una molestia porque tienes que expresar la entrada al constructor RegExp como una cadena en lugar de usar las barras diagonales / [AZ] + / regexp formato literal)

Jason S
fuente
3

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 real de la variable.

Alex Li
fuente
2

Puede usar esto si $ 1 no funciona con usted

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

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 bucle infinito cuando el reemplazo contiene la coincidencia.

Ry-
fuente
1

Tu solución está aquí:

Pase una variable a la 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 más. En mi caso estoy usando Jquery, 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, puede ponerlo en una función para llamar.

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

Ajit Hogade
fuente
Su variable replace_with contendrá el elemento DOM, no el valor en sí mismo
Ben Taliadoros
1

Esta función de llamada automática iterará sobre reemplacerItems usando un índice y cambiará reemplacerItems [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'

fuente
0

Ninguna de estas respuestas fue clara para mí. Finalmente encontré una buena explicación en http://burnignorance.com/php-programming-tips/how-to-use-a-variable-in-replace-function-of-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>

Paul Chris Jones
fuente
1
Está sobrescribiendo una variable de cierre, no es necesario usarla varaquí. Además, si pasa \bo \1se rompería.
CyberAP
0

Para el 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í.

John Shearing
fuente