Respuestas:
Aquí se explica cómo crear una expresión regular sin usar la sintaxis literal de la expresión regular. Esto le permite realizar una manipulación arbitraria de cadenas antes de que se convierta en un objeto de expresión regular:
var segment_part = "some bit of the regexp";
var pattern = new RegExp("some regex segment" + /*comment here */
segment_part + /* that was defined just now */
"another segment");
Si tiene dos literales de expresión regular, de hecho puede concatenarlos utilizando esta técnica:
var regex1 = /foo/g;
var regex2 = /bar/y;
var flags = (regex1.flags + regex2.flags).split("").sort().join("").replace(/(.)(?=.*\1)/g, "");
var regex3 = new RegExp(expression_one.source + expression_two.source, flags);
// regex3 is now /foobar/gy
Es simplemente más prolijo que simplemente tener la expresión uno y dos como cadenas literales en lugar de expresiones regulares literales.
new RegExp(/(/.source + /.*/.source + /)?/.source);
no parece funcionar.
expression_one
? Qué quiere decir regex1
?
Solo concatenar aleatoriamente objetos de expresiones regulares puede tener algunos efectos secundarios adversos. Utilice RegExp.source en su lugar:
var r1 = /abc/g;
var r2 = /def/;
var r3 = new RegExp(r1.source + r2.source,
(r1.global ? 'g' : '')
+ (r1.ignoreCase ? 'i' : '') +
(r1.multiline ? 'm' : ''));
console.log(r3);
var m = 'test that abcdef and abcdef has a match?'.match(r3);
console.log(m);
// m should contain 2 matches
Esto también le dará la capacidad de retener los indicadores de expresión regular de un RegExp anterior utilizando los indicadores RegExp estándar.
RegExp.prototype.flags
No estoy del todo de acuerdo con la opción "eval".
var xxx = /abcd/;
var yyy = /efgh/;
var zzz = new RegExp(eval(xxx)+eval(yyy));
dará "// abcd // efgh //", que no es el resultado deseado.
Usando fuente como
var zzz = new RegExp(xxx.source+yyy.source);
dará "/ abcdefgh /" y eso es correcto.
Lógicamente no hay necesidad de EVALUAR, ya sabes tu EXPRESIÓN. Solo necesita su FUENTE o cómo está escrito, no necesariamente su valor. En cuanto a las banderas, solo necesita usar el argumento opcional de RegExp.
En mi situación, corro el problema de que ^ y $ se usan en varias expresiones ¡Estoy tratando de concatenar juntos! Esas expresiones son filtros gramaticales utilizados en todo el programa. Ahora quiero usar algunos de ellos juntos para manejar el caso de PREPOSICIONES. Puede que tenga que "cortar" las fuentes para eliminar el principio y el final ^ (y / o) $ :) Saludos, Alex.
var regex = "\.\..*"
Problema Si el regexp contiene grupos de correspondencia inversa como \ 1.
var r = /(a|b)\1/ // Matches aa, bb but nothing else.
var p = /(c|d)\1/ // Matches cc, dd but nothing else.
Entonces simplemente contactando las fuentes no funcionará. De hecho, la combinación de los dos es:
var rp = /(a|b)\1(c|d)\1/
rp.test("aadd") // Returns false
La solución: primero contamos el número de grupos coincidentes en la primera expresión regular, luego para cada ficha de coincidencia inversa en el segundo, lo incrementamos por el número de grupos coincidentes.
function concatenate(r1, r2) {
var count = function(r, str) {
return str.match(r).length;
}
var numberGroups = /([^\\]|^)(?=\((?!\?:))/g; // Home-made regexp to count groups.
var offset = count(numberGroups, r1.source);
var escapedMatch = /[\\](?:(\d+)|.)/g; // Home-made regexp for escaped literals, greedy on numbers.
var r2newSource = r2.source.replace(escapedMatch, function(match, number) { return number?"\\"+(number-0+offset):match; });
return new RegExp(r1.source+r2newSource,
(r1.global ? 'g' : '')
+ (r1.ignoreCase ? 'i' : '')
+ (r1.multiline ? 'm' : ''));
}
Prueba:
var rp = concatenate(r, p) // returns /(a|b)\1(c|d)\2/
rp.test("aadd") // Returns true
function concatenateList() { var res = arguments[0]; for(var i = 1; i < arguments.length; i++) { res = concatenate(res, arguments[i]); } return res; }
Sería preferible utilizar la sintaxis literal tan a menudo como sea posible. Es más corto, más legible, y no necesita comillas de escape o contragolpes de doble escape. De "Patrones Javascript", Stoyan Stefanov 2010.
Pero usar New puede ser la única forma de concatenar.
Yo evitaría eval. No es seguro.
Siempre que:
/this/g
lugar de new RegExp('this', 'g')
;Entonces te gustaría escribir de esta manera:
var regexParts =
[
/\b(\d+|null)\b/,// Some comments.
/\b(true|false)\b/,
/\b(new|getElementsBy(?:Tag|Class|)Name|arguments|getElementById|if|else|do|null|return|case|default|function|typeof|undefined|instanceof|this|document|window|while|for|switch|in|break|continue|length|var|(?:clear|set)(?:Timeout|Interval))(?=\W)/,
/(\$|jQuery)/,
/many more patterns/
],
regexString = regexParts.map(function(x){return x.source}).join('|'),
regexPattern = new RegExp(regexString, 'g');
entonces puedes hacer algo como:
string.replace(regexPattern, function()
{
var m = arguments,
Class = '';
switch(true)
{
// Numbers and 'null'.
case (Boolean)(m[1]):
m = m[1];
Class = 'number';
break;
// True or False.
case (Boolean)(m[2]):
m = m[2];
Class = 'bool';
break;
// True or False.
case (Boolean)(m[3]):
m = m[3];
Class = 'keyword';
break;
// $ or 'jQuery'.
case (Boolean)(m[4]):
m = m[4];
Class = 'dollar';
break;
// More cases...
}
return '<span class="' + Class + '">' + m + '</span>';
})
En mi caso particular (un editor similar al código espejo), es mucho más fácil realizar una gran expresión regular, en lugar de muchos reemplazos como el siguiente, ya que cada vez que reemplazo con una etiqueta html para ajustar una expresión, el siguiente patrón será ser más difícil de apuntar sin afectar la etiqueta html en sí (y sin el buen aspecto que desafortunadamente no es compatible con javascript):
.replace(/(\b\d+|null\b)/g, '<span class="number">$1</span>')
.replace(/(\btrue|false\b)/g, '<span class="bool">$1</span>')
.replace(/\b(new|getElementsBy(?:Tag|Class|)Name|arguments|getElementById|if|else|do|null|return|case|default|function|typeof|undefined|instanceof|this|document|window|while|for|switch|in|break|continue|var|(?:clear|set)(?:Timeout|Interval))(?=\W)/g, '<span class="keyword">$1</span>')
.replace(/\$/g, '<span class="dollar">$</span>')
.replace(/([\[\](){}.:;,+\-?=])/g, '<span class="ponctuation">$1</span>')
Podrías hacer algo como:
function concatRegex(...segments) {
return new RegExp(segments.join(''));
}
Los segmentos serían cadenas (en lugar de literales regex) pasadas como argumentos separados.
Utilice el constructor con 2 parámetros y evite el problema con el final '/':
var re_final = new RegExp("\\" + ".", "g"); // constructor can have 2 params!
console.log("...finally".replace(re_final, "!") + "\n" + re_final +
" works as expected..."); // !!!finally works as expected
// meanwhile
re_final = new RegExp("\\" + "." + "g"); // appends final '/'
console.log("... finally".replace(re_final, "!")); // ...finally
console.log(re_final, "does not work!"); // does not work
Puede concat fuente de expresiones regulares tanto de la clase literal como de la clase RegExp:
var xxx = new RegExp(/abcd/);
var zzz = new RegExp(xxx.source + /efgh/.source);
la forma más fácil para mí sería concatenar las fuentes, ej .:
a = /\d+/
b = /\w+/
c = new RegExp(a.source + b.source)
el valor c dará como resultado:
/ \ d + \ w + /
let regexSegment1 = String.raw`\s*hello\s*`