En el momento del inicio de sesión, debo permitir solo el nombre de usuario (alfanumérico y algunos caracteres especiales) o la dirección de correo electrónico o el formato de nombre de usuario\dominio. Para este propósito, utilicé esta expresión regular con la condición o ( | ). Junto con esto, necesito permitir algunos otros caracteres de idioma como japonés, chino, etc., por lo que también los incluí en la misma expresión regular. Ahora, el problema es que cuando ingreso caracteres (>=30) y @ o algún carácter especial, la evaluación de esta expresión regular tarda unos segundos y el navegador entra en modo de bloqueo.
export const usernameRegex = /(^[a-zA-Z0-9._~^#!%+\-]+@[a-z0-9.-]+\.[az]{2,4})+|^[a-zA-Z0-9._~^#!\-]+\\([._-~^#!]|[\p{Ll}\p{Lm}\p{Lt}a-zA-Z0-9-\u3000-\u303f\u3040-\u309f\u30a0-\u30ff\uff00-\uff9f\u4e00-\u9faf\u3400-\u4dbf\u3130-\u318F\uAC00-\uD7AF])+|^([._-~^#!]|[\p{Ll}\p{Lm}\p{Lt}a-zA-Z0-9-\u3000-\u303f\u3040-\u309f\u30a0-\u30ff\uff00-\uff9f\u4e00-\u9faf\u3400-\u4dbf\u3130-\u318F\uAC00-\uD7AF])+$/gu; Cuando intenté eliminar el conjunto de caracteres de otro idioma, como [\p{Ll}\p{Lm}\p{Lt}a-zA-Z0-9-\u3000-\u303f\u3040-\u309f\u30a0-\u30ff\uff00-\uff9f\u4e00-\u9faf\u3400-\u4dbf\u3130-\u318F\uAC00-\uD7AF])+|^([._-~^#!]|[\p{Ll}\p{Lm}\p{Lt}a-zA-Z0-9-\u3000-\u303f\u3040-\u309f\u30a0-\u30ff\uff00-\uff9f\u4e00-\u9faf\u3400-\u4dbf\u3130-\u318F\uAC00-\uD7AF] funciona bien.
Entendí que, en general, la expresión regular parece simple pero hace mucho debajo del capó. ¿Hay alguna modificación que deba hacerse en esta expresión regular, para que no tome tiempo evaluarla? ¡Cualquier ayuda es muy apreciada!
Textos válidos:
stackoverflow, stackoverflow1~, stackoverflow!#~^-, stackoverflow@g.co, stackoverflow!#~^-@g.co,こんにちは,你好, tree\guavaEDITAR:
por ejemplo, Entrada que causa el problema stackoverflowstackoverflowstackoverflow@
Al dar el texto anterior, está tomando mucho tiempo.
Su expresión regular parece consistir en tres expresiones regulares concatenadas con |
(^[a-zA-Z0-9._~^#!%+\-]+@[a-z0-9.-]+\.[az]{2,4})+ ^[a-zA-Z0-9._~^#!\-]+\\([._-~^#!]|[\p{Ll}\p{Lm}\p{Lt}a-zA-Z0-9-\u3000-\u303f\u3040-\u309f\u30a0-\u30ff\uff00-\uff9f\u4e00-\u9faf\u3400-\u4dbf\u3130-\u318F\uAC00-\uD7AF])+ ^([._-~^#!]|[\p{Ll}\p{Lm}\p{Lt}a-zA-Z0-9-\u3000-\u303f\u3040-\u309f\u30a0-\u30ff\uff00-\uff9f\u4e00-\u9faf\u3400-\u4dbf\u3130-\u318F\uAC00-\uD7AF])+$ primera expresión regular (^...)+ cuántas veces cree que puede ocurrir todo este patrón que comienza al principio de la cadena. O es una segunda ocurrencia O comienza al principio de la cadena, no pueden ser ambas.
Entonces ^[a-zA-Z0-9._~^#!%+\-]+@[a-z0-9.-]+\.[az]{2,4}
las partes 2 y 3 son en su mayoría idénticas, solo que nr. 2 contiene este bloque [a-zA-Z0-9._~^#!\-]+\\ seguido del resto de la tercera parte.
Así que combinémoslos: ^(?:[a-zA-Z0-9._~^#!\-]+\\)? ... y asegúrese de usar grupos que no capturen cuando sea posible.
([abc]|[def])+ se puede simplificar a [abcdef]+ . Esto por cierto. es la parte que está matando tu interpretación.
su expresión regular termina con $ . Esto fue solo una parte de la última parte, pero supongo que siempre querrás hacer coincidir la cadena completa. Así que hagamos las 3 (ahora 2) partes ^ ... $
Resumen:
/^[a-zA-Z0-9._~^#!%+-]+@[a-z0-9.-]+\.[az]{2,4}$|^(?:[a-zA-Z0-9._~^#!-]+\\)?[._-~^#!\p{Ll}\p{Lm}\p{Lt}a-zA-Z0-9-\u3000-\u303f\u3040-\u309f\u30a0-\u30ff\uff00-\uff9f\u4e00-\u9faf\u3400-\u4dbf\u3130-\u318F\uAC00-\uD7AF]+$/u Un ejemplo de JS de cómo una expresión regular simple intentaría hacer coincidir una cadena, y cómo falla, retrocede, vuelve a intentar con el otro lado de la | Y así sucesivamente y así sucesivamente.
// let's implement what `/([az]|[\p{Ll}])+/u` would do, // how it would try to match something. const a = /[az]/; // left part const b = /[\p{Ll}]/u; // right part const string = "abc,"; const testNextCharacter = (index) => { if (index === string.length) { return true; } const pattern = index + " ".repeat(index + 1) + "%o.test(%o)"; const character = string.charAt(index); console.log(pattern, a, character); // checking the left part && if successful checking the next character if (a.test(character) && testNextCharacter(index + 1)) { return true; } // checking the right part && if successful checking the next character console.log(pattern, b, character); if (b.test(character) && testNextCharacter(index + 1)) { return true; } return false; } console.log("result", testNextCharacter(0)); .as-console-wrapper{top:0;max-height:100%!important}Y esto son sólo 4 caracteres. ¿Por qué no intenta esto con 5,6 caracteres para tener una idea de cuánto trabajo será con 20 caracteres?