Nothing to repeat error

4

This code what does is find in a string the indexes of "[" and "]" , then with substring, I only take the part inside the brackets.

Then I draw them in a canvas according to the if:

  • a string that is without the content of the brackets (including also the elimination of the brackets itself),
  • and another one where only the contents of the brackets are shown.

And everything is normal, but sometimes, very rarely, unexpectedly I get the error:

  

Nothing to repeat error

Why is this happening?

var b = this.name.indexOf("["); // Busca el [
var c = this.name.indexOf("]"); // Busca el ]
var mostrar = this.name.substring(b, c + 1);
mostrar = mostrar.replace(/[\[\]']+/g,'');
var d = c - b;


if(d > 1 && nameDraw && mostrar != '') {
    var t = this.name.replace(new RegExp(mostrar, 'g'), '');
    t = t.replace(/\[.*?\]/g, '');
    drawText(this.x - 4, this.y, t, this._nameSize, false);
    drawText(this.x, this.y - 62, mostrar, this._nameSize, false);
}
    
asked by Eduardo Sebastian 29.06.2017 в 13:48
source

1 answer

5

Nothing to repeat is a syntax error within your regular expression. It means that there is a quantifier ( * , ? , + , {m,n} ) that is in a position where it has nothing to repeat. Usually it happens with a quantifier at the beginning of the expression, or with one quantifier after another (invalid).

  

It is common to see it when a special character for the regular expression is not escaping correctly.

/*  Ejemplo  */
var regex = /abc++?/; //El segundo + no está repitiendo nada!!!


For your case in particular, it happens because you are generating a regex dynamically from a text without escaping the special characters. When the user enters something such as this.name="Genera [error???]" , you are trying to generate a regex with "error???" , which is an invalid expression.

To generate a literal regex from a string, you have to escape using this function

function escaparRegex(string) {
    return string.replace(/[\^$.|?*+()[{]/g, '\$&'); 
}


Code

Let's forget about the problem of escaping the text, let's simplify.

We're going to use the regex /\[([^\]]*)\]/ .

  • \[ - literal bracket.
  • ( ... ) - Capturing group. Generates a reference with the text with which it coincided.
    Coincides with:
    • [^\]]* - One character, any except ']' , repeated ( * ) 0 or more times.
      That is, " matches all characters other than ] ".
  • \] - literal bracket.


On the replace () , instead of pass a string, we can go to an anonymous function that will be called to evaluate the replacement of the regex.

function entreCorchetes (texto) {
    var regex = /\[([^\]]*)\]/,
        resultado;
    
    resultado = texto.replace(regex, function(m, mostrar) {
        if (mostrar !== '') { //si tiene texto
            //Y acá llamarías a drawText
            console.log('Entre corchetes:', mostrar);
        }
        return ''; //reemplazamos por "" (eliminamos)
    });
    
    return resultado;
}



// EJEMPLO

var original = "Prueba [abc+++]";
console.log("Original:", original);

var final = entreCorchetes(original); //llamamos a la función (elimina el primer texto entre corchetes que encuentre)
console.log("Final:", final);

The anonymous function receives as parameters the string with which the regex coincided, and then a parameter for each capture made by each group.

In the regex /\[([^\]]*)\]/ we use 1 set of parentheses, to capture the text that is inside the brackets. In other words, the function will receive as the first parameter ( m ) the text with brackets, and as the second parameter ( mostrar ) the same text, but without the brackets.

The result of the function is what will be used effectively in the replacement of the string. That is why we always return '' (empty text), so that the brackets of the original string are eliminated. It is the same as doing, texto.replace( regex, ''); , but evaluating the match in the function.


  

What if we try something simpler?

     

In these questions, I always ask myself if it is not convenient to simplify everything and use classic string management functions. Why start with revolts of regex and nested anonymous functions? Is it fashionable? Does it seem more "pro"? How many lines do we save?

     

The only thing you're looking for is:

     
  • Obtain the first occurrence of a text in brackets (print it without brackets).
  •   
  • Eliminate that occurrence of the string, also eliminating the brackets (print it).
  •   

    Step by step, with comments in the code:

         

     
    //Usemos un ejemplo
    var name = 'Mariano] [clan][no eliminar]';
    //Las variables para el resultado
    var texto,
        mostrar = "";
    
    
    //Busquemos el primer "["
    var posInicial = name.indexOf('[');
    
    if (posInicial >= 0) { //Encontramos un "["
    
        //Ahora buscamos la posición de un "]" DESDE la anterior
        var posFinal = name.indexOf(']', posInicial + 1);
        
        if (posFinal >= 0) { //Encontramos un "]"
        
            //Obtenemos el clan
            mostrar = name.substring(posInicial + 1, posFinal);
            
            //Obtenemos el texto sin los primeros corchetes
            // (del inicio hasta antes del que abre + despues del que cierra hasta el final)
            texto = name.substr(0, posInicial) + name.substr(posFinal + 1);
        
        } else { //No tiene ningún "]" luego del "["
            //Creo que acá no harías nada, no sé, fijate
            texto = name;
        }
        
    } else { //No tiene ningún "["
        //Creo que acá no harías nada, no sé, fijate
        texto = name;
    }
    
    
    //Mostremos el resultado
    console.log("Original:", name);
    console.log("Posiciones:", posInicial, posFinal);
    console.log("Final:", texto);
    console.log("Clan:", mostrar);
        
    answered by 29.06.2017 / 17:42
    source