JavaScript - backreferences de cadenas de expresiones regulares


93

Puede hacer una referencia inversa como esta en JavaScript:

var str = "123 $test 123";
str = str.replace(/(\$)([a-z]+)/gi, "$2");

Esto (bastante tonto) reemplazaría "$ test" por "test". Pero imagina que me gustaría pasar la cadena resultante de $ 2 a una función, que devuelve otro valor. Intenté hacer esto, pero en lugar de obtener la cadena "prueba", obtengo "$ 2". ¿Hay una manera de lograr esto?

// Instead of getting "$2" passed into somefunc, I want "test"
// (i.e. the result of the regex)
str = str.replace(/(\$)([a-z]+)/gi, somefunc("$2"));

Respuestas:


117

Me gusta esto:

str.replace(regex, function(match, $1, $2, offset, original) { return someFunc($2); })

1
Genial, ¿dónde puedo encontrar más información sobre esto?
Quano


11
Frio. Para aclarar: $1y $2son los nombres de los parámetros elegidos por el usuario aquí (elegidos para imitar los símbolos de referencia inversa); el - ¡variando! - el número de estos parámetros corresponde al número de grupos de captura en la expresión regular.
mklement0

34

Pase una función como segundo argumento a replace:

str = str.replace(/(\$)([a-z]+)/gi, myReplace);

function myReplace(str, group1, group2) {
    return "+" + group2 + "+";
}

Esta capacidad ha existido desde Javascript 1.3, según mozilla.org .


1

Usando ESNext, todo un sustituto de enlaces ficticios, pero solo para mostrar cómo funciona:

let text = 'Visit http://lovecats.com/new-posts/ and https://lovedogs.com/best-dogs NOW !';

text = text.replace(/(https?:\/\/[^ ]+)/g, (match, link) => {
  // remove ending slash if there is one
  link = link.replace(/\/?$/, '');
  
  return `<a href="${link}" target="_blank">${link.substr(link.lastIndexOf('/') +1)}</a>`;
});

document.body.innerHTML = text;


0

Nota: En la respuesta anterior faltaba algún código. Ahora es fijo + ejemplo.


Necesitaba algo un poco más flexible para un reemplazo de expresiones regulares para decodificar el Unicode en mis datos JSON entrantes:

var text = "some string with an encoded '&#115;' in it";

text.replace(/&#(\d+);/g, function() {
  return String.fromCharCode(arguments[1]);
});

// "some string with an encoded 's' in it"

0

Si tuviera una cantidad variable de referencias inversas, entonces el recuento de argumentos (y los lugares) también son variables. Los documentos web de MDN describen la siguiente sintaxis para separar una función como argumento de reemplazo:

function replacer(match[, p1[, p2[, p...]]], offset, string)

Por ejemplo, tome estas expresiones regulares:

var searches = [
    'test([1-3]){1,3}',  // 1 backreference
    '([Ss]ome) ([A-z]+) chars',  // 2 backreferences
    '([Mm][a@]ny) ([Mm][0o]r[3e]) ([Ww][0o]rd[5s])'  // 3 backreferences
];
for (var i in searches) {
    "Some string chars and many m0re w0rds in this test123".replace(
        new RegExp(
            searches[i]
            function(...args) {
                var match = args[0];
                var backrefs = args.slice(1, args.length - 2);
                // will be: ['Some', 'string'], ['many', 'm0re', 'w0rds'], ['123']
                var offset = args[args.length - 2];
                var string = args[args.length - 1];
            }
        )
    );
}

No puede usar la variable 'argumentos' aquí porque es de tipo Argumentsy no de tipo, Arraypor lo que no tiene un slice()método.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.