Conversión de la cadena de entrada del usuario en una expresión regular

Estoy diseñando un probador de expresiones regulares en HTML y JavaScript. El usuario ingresará una expresión regular, una cadena y elegirá la función con la que desea probar (por ejemplo, buscar, emparejar, reemplazar, etc.) a través del botón de radio y el programa mostrará los resultados cuando esa función se ejecute con los argumentos especificados. Naturalmente, habrá cuadros de texto adicionales para reemplazar los argumentos adicionales y demás.

Mi problema es obtener la cadena del usuario y convertirla en una expresión regular. Si digo que no necesitan tener //está alrededor de la expresión regular en la que ingresan, entonces no pueden establecer banderas, como g e i. Entonces tienen que tener el //está alrededor de la expresión, pero ¿cómo puedo convertir esa cadena en una expresión regular? No puede ser un literal ya que es una cadena, y no puedo pasarlo al constructor RegExp ya que no es una cadena sin el //'s. ¿Hay alguna otra forma de convertir una cadena de entrada de usuario en una expresión regular? ¿Tendré que analizar la cadena y las banderas de la expresión regular con el //Entonces, ¿construirlo de otra manera? ¿Debería hacer que ingresen una cadena y luego ingresar las banderas por separado?

preguntado el 17 de mayo de 09 a las 11:05

11 Respuestas

Use el Constructor de objetos RegExp para crear una expresión regular a partir de una cadena:

var re = new RegExp("a|b", "i");
// same as
var re = /a|b/i;

contestado el 17 de mayo de 09 a las 15:05

Sería bueno tener una herramienta en línea con un campo de entrada. encinas

Al hacerlo de esta manera, debe escapar de la barra invertida, p. Ej. var re = new RegExp("\\w+"); - JD Smith

@holms Regex101.com también es una gran herramienta en línea de expresiones regulares - fran herrero

Me tomó un tiempo ver que no se requieren barras al final - gerfried

@JDSmith No lo dije en serio en tu ejemplo. Quise decir que debe escapar de las comillas dobles si desea que formen parte de la expresión regular siempre que esté codificada. Obviamente, nada de esto se aplica si la cadena está en una variable como de un <input> Etiqueta HTML. var re = new RegExp("\"\\w+\""); es un ejemplo de una expresión regular codificada de forma rígida que utiliza el constructor RegExp y el escape de las comillas dobles is necesario. Lo que quiero decir con una cadena en una variable es que puedes hacer var re = new RegExp(str); e str puede contener comillas dobles o barras invertidas sin problemas. - Luis paulo

var flags = inputstring.replace(/.*\/([gimy]*)$/, '$1');
var pattern = inputstring.replace(new RegExp('^/(.*?)/'+flags+'$'), '$1');
var regex = new RegExp(pattern, flags);

or

var match = inputstring.match(new RegExp('^/(.*?)/([gimy]*)$'));
// sanity check here
var regex = new RegExp(match[1], match[2]);

Respondido el 09 de Septiembre de 14 a las 14:09

Debe considerar que una entrada no válida como /\/ es reconocido. - Gumbo

O deje que el constructor de RegExp falle, "finalizando \ en una expresión regular", en lugar de escribir un analizador complicado. - Anónimo

Aquí hay un resumen: str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&')

Lo obtuve del cadena de escape-regexp Módulo NPM.

Probándolo:

escapeStringRegExp.matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
function escapeStringRegExp(str) {
    return str.replace(escapeStringRegExp.matchOperatorsRe, '\\$&');
}

console.log(new RegExp(escapeStringRegExp('example.com')));
// => /example\.com/

Uso de literales de plantilla etiquetados con compatibilidad con banderas:

function str2reg(flags = 'u') {
    return (...args) => new RegExp(escapeStringRegExp(evalTemplate(...args))
        , flags)
}

function evalTemplate(strings, ...values) {
    let i = 0
    return strings.reduce((str, string) => `${str}${string}${
        i < values.length ? values[i++] : ''}`, '')
}

console.log(str2reg()`example.com`)
// => /example\.com/u

Respondido 10 Abr '20, 14:04

Use el Constructor de objetos JavaScript RegExp.

var re = new RegExp("\\w+");
re.test("hello");

Puede pasar banderas como un segundo argumento de cadena al constructor. Consulte la documentación para obtener más detalles.

contestado el 17 de mayo de 09 a las 15:05

En mi caso, la entrada del usuario algunas veces estaba rodeada de delimitadores y otras veces no. por eso agregué otro caso ..

var regParts = inputstring.match(/^\/(.*?)\/([gim]*)$/);
if (regParts) {
    // the parsed pattern had delimiters and modifiers. handle them. 
    var regexp = new RegExp(regParts[1], regParts[2]);
} else {
    // we got pattern string without delimiters
    var regexp = new RegExp(inputstring);
}

respondido 31 mar '14, 15:03

siempre puedes usar el .split() función en lugar de una larga cadena de expresiones regulares. regParts = inputstring.split('/') esto haría regParts[1] la cadena de expresiones regulares, y regParts[2] los delimitadores (asumiendo que la configuración de la expresión regular es /.../gim). Puede comprobar si hay delimitadores con regParts[2].length < 0. - ZomoXYZ

Intente usar la siguiente función:

const stringToRegex = str => {
    // Main regex
    const main = str.match(/\/(.+)\/.*/)[1]
    
    // Regex options
    const options = str.match(/\/.+\/(.*)/)[1]
    
    // Compiled regex
    return new RegExp(main, options)
}

Puedes usarlo así:

"abc".match(stringToRegex("/a/g"))
//=> ["a"]

Respondido el 20 de Septiembre de 20 a las 03:09

Le sugiero que también agregue casillas de verificación separadas o un campo de texto para las banderas especiales. De esa forma, queda claro que el usuario no necesita agregar ningún //'s. En el caso de un reemplazo, proporcione dos campos de texto. Esto hará tu vida mucho más fácil.

¿Por qué? Porque de lo contrario algunos usuarios agregarán //mientras que otros no lo harán. Y algunos cometerán un error de sintaxis. Luego, después de que te quitaste el //, puede terminar con una expresión regular sintácticamente válida que no se parece en nada a lo que pretendía el usuario, lo que lleva a un comportamiento extraño (desde la perspectiva del usuario).

Respondido 30 Jul 13, 22:07

Esto también funcionará cuando la cadena no sea válida o no contenga banderas, etc.

function regExpFromString(q) {
  let flags = q.replace(/.*\/([gimuy]*)$/, '$1');
  if (flags === q) flags = '';
  let pattern = (flags ? q.replace(new RegExp('^/(.*?)/' + flags + '$'), '$1') : q);
  try { return new RegExp(pattern, flags); } catch (e) { return null; }
}

console.log(regExpFromString('\\bword\\b'));
console.log(regExpFromString('\/\\bword\\b\/gi'));
            

Respondido el 09 de Septiembre de 16 a las 08:09

Gracias a las respuestas anteriores, estos bloques sirven como una solución de propósito general para aplicar una cadena configurable en una expresión regular ... para filtrar texto:

var permittedChars = '^a-z0-9 _,.?!@+<>';
permittedChars = '[' + permittedChars + ']';

var flags = 'gi';
var strFilterRegEx = new RegExp(permittedChars, flags);

log.debug ('strFilterRegEx: ' + strFilterRegEx);

strVal = strVal.replace(strFilterRegEx, '');
// this replaces hard code solt:
// strVal = strVal.replace(/[^a-z0-9 _,.?!@+]/ig, '');

Respondido el 21 de Septiembre de 15 a las 02:09

Puede solicitar banderas usando casillas de verificación y luego hacer algo como esto:

var userInput = formInput;
var flags = '';
if(formGlobalCheckboxChecked) flags += 'g';
if(formCaseICheckboxChecked) flags += 'i';
var reg = new RegExp(userInput, flags);

Respondido el 09 de junio de 17 a las 19:06

de verdad RegEx falta al final p .. Stack no me dejaba hacer una edición de 1 carácter - gen bo

yo suelo eval para resolver este problema.

Por ejemplo:

    function regex_exec() {

        // Important! Like @Samuel Faure mentioned, Eval on user input is a crazy security risk, so before use this method, please take care of the security risk. 
        var regex = $("#regex").val();

        // eval()
        var patt = eval(userInput);

        $("#result").val(patt.exec($("#textContent").val()));
    }

Respondido 23 Jul 19, 09:07

eval en userInput es un riesgo de seguridad loco - Samuel Fauré

mr bobby tables! - Luiz felipe

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.