Nuevas funciones de JavaScript que cambiarán la forma de escribir expresiones regulares

 

 

 

  • Patrones de diseño de interfaces inteligentes, vídeo de 10h + formación UX
  • Design Token and UI Component Architecture, with Nathan Curtis

  • Índice
    1. Afirmaciones retrospectivas
    2. Grupos de captura con nombre
    3. s( dotAll) Bandera
    4. Escapes de propiedad Unicode
    5. Tabla de compatibilidad
      1. Navegadores de escritorio
      2. Navegadores móviles
      3. Nodo.js
    6. Terminando

    Si alguna vez ha realizado algún tipo de manipulación y procesamiento de texto sofisticado en JavaScript, apreciará las nuevas funciones introducidas en ES2018. En este artículo, analizamos detenidamente cómo la novena edición del estándar mejora la capacidad de procesamiento de texto de JavaScript.

     

    Hay una buena razón por la que la mayoría de los lenguajes de programación admiten expresiones regulares: son herramientas extremadamente poderosas para manipular texto. Las tareas de procesamiento de texto que requieren docenas de líneas de código a menudo se pueden realizar con una sola línea de código de expresión regular. Si bien las funciones integradas en la mayoría de los idiomas suelen ser suficientes para realizar operaciones de búsqueda y reemplazo en cadenas, las operaciones más complejas, como la validación de entradas de texto, a menudo requieren el uso de expresiones regulares.

    Las expresiones regulares han sido parte del lenguaje JavaScript desde la tercera edición del estándar ECMAScript, que se introdujo en 1999. ECMAScript 2018 (o ES2018 para abreviar) es la novena edición del estándar y mejora aún más la capacidad de procesamiento de texto de JavaScript al introducir cuatro nuevas características:

     

    • Afirmaciones retrospectivas
    • Grupos de captura con nombre
    • s( dotAll) Bandera
    • La propiedad Unicode se escapa

    Estas nuevas características se explican en detalle en las subsecciones siguientes.

    Depuración de JavaScript

    console.logpuede decirle mucho sobre su aplicación, pero realmente no puede depurar su código. Para eso, necesita un depurador de JavaScript completo.Leer un artículo relacionado →

    Afirmaciones retrospectivas

    La capacidad de hacer coincidir una secuencia de caracteres en función de lo que sigue o precede le permite descartar coincidencias potencialmente no deseadas. Esto es especialmente importante cuando necesita procesar una cadena grande y la posibilidad de que se produzcan coincidencias no deseadas es alta. Afortunadamente, la mayoría de los tipos de expresiones regulares proporcionan aserciones de búsqueda hacia atrás y hacia adelante para este propósito.

    Antes de ES2018, solo las aserciones anticipadas estaban disponibles en JavaScript. Una anticipación le permite afirmar que un patrón es seguido inmediatamente por otro patrón.

    Hay dos versiones de aserciones anticipadas: positivas y negativas. La sintaxis para una anticipación positiva es (?=...). Por ejemplo, la expresión regular /Item(?= 10)/coincide Itemsolo cuando va seguida, con un espacio intermedio, del número 10:

    const re = /Item(?= 10)/;console.log(re.exec('Item'));// → nullconsole.log(re.exec('Item5'));// → nullconsole.log(re.exec('Item 5'));// → nullconsole.log(re.exec('Item 10'));// → ["Item", index: 0, input: "Item 10", groups: undefined]

    Este código utiliza el exec()método para buscar una coincidencia en una cadena. Si se encuentra una coincidencia, exec()devuelve una matriz cuyo primer elemento es la cadena coincidente. La indexpropiedad de la matriz contiene el índice de la cadena coincidente y la inputpropiedad contiene la cadena completa en la que se realizó la búsqueda. Finalmente, si se utilizan grupos de captura con nombre en la expresión regular, se colocan en la groupspropiedad. En este caso, groupstiene el valor de undefinedporque no hay ningún grupo de captura con nombre.

    El constructo para una anticipación negativa es (?!...). Una anticipación negativa afirma que un patrón no es seguido por un patrón específico. Por ejemplo, el patrón /Red(?!head)/coincide Redsólo si no va seguido de head:

    const re = /Red(?!head)/;console.log(re.exec('Redhead'));// → nullconsole.log(re.exec('Redberry'));// → ["Red", index: 0, input: "Redberry", groups: undefined]console.log(re.exec('Redjay'));// → ["Red", index: 0, input: "Redjay", groups: undefined]console.log(re.exec('Red'));// → ["Red", index: 0, input: "Red", groups: undefined]

    ES2018 complementa las aserciones de búsqueda anticipada al incorporar aserciones de búsqueda atrás a JavaScript. Indicada por (?=...), una aserción de búsqueda hacia atrás le permite hacer coincidir un patrón solo si está precedido por otro patrón.

     

    Supongamos que necesita recuperar el precio de un producto en euros sin capturar el símbolo del euro. Con una mirada atrás, esta tarea se vuelve mucho más sencilla:

    const re = /(?=€)d+(.d*)?/;console.log(re.exec('199'));// → nullconsole.log(re.exec('$199'));// → nullconsole.log(re.exec('€199'));// → ["199", undefined, index: 1, input: "€199", groups: undefined]

    Nota : Las aserciones de búsqueda hacia adelante y hacia atrás a menudo se denominan “búsquedas”.

    La versión negativa de la búsqueda hacia atrás se indica con (?!...)y le permite hacer coincidir un patrón que no está precedido por el patrón especificado en la búsqueda hacia atrás. Por ejemplo, la expresión regular /(?!d{3}) meters/coincide con la palabra "metros" si no van tres dígitos delante:

    const re = /(?!d{3}) meters/;console.log(re.exec('10 meters'));// → [" meters", index: 2, input: "10 meters", groups: undefined]console.log(re.exec('100 meters')); // → null

    Al igual que con las miradas hacia adelante, puede utilizar varias miradas hacia atrás (negativas o positivas) seguidas para crear un patrón más complejo. He aquí un ejemplo:

    const re = /(?=d{2})(?!35) meters/;console.log(re.exec('35 meters'));// → nullconsole.log(re.exec('meters'));// → nullconsole.log(re.exec('4 meters'));// → nullconsole.log(re.exec('14 meters'));// → ["meters", index: 2, input: "14 meters", groups: undefined]

    Esta expresión regular coincide con una cadena que contiene metros solo si está inmediatamente precedida por dos dígitos cualesquiera que no sean 35. La búsqueda hacia atrás positiva garantiza que el patrón esté precedido por dos dígitos, y luego la búsqueda hacia atrás negativa garantiza que los dígitos no sean 35.

    Grupos de captura con nombre

    Puede agrupar una parte de una expresión regular encapsulando los caracteres entre paréntesis. Esto le permite restringir la alternancia a una parte del patrón o aplicar un cuantificador a todo el grupo. Además, puede extraer el valor coincidente entre paréntesis para su posterior procesamiento.

    El siguiente código ofrece un ejemplo de cómo encontrar un nombre de archivo con extensión .jpg en una cadena y luego extraer el nombre del archivo:

    const re = /(w+).jpg/;const str = 'File name: cat.jpg';const match = re.exec(str);const fileName = match[1];// The second element in the resulting array holds the portion of the string that parentheses matchedconsole.log(match);// → ["cat.jpg", "cat", index: 11, input: "File name: cat.jpg", groups: undefined]console.log(fileName);// → cat

    En patrones más complejos, hacer referencia a un grupo usando un número simplemente hace que la ya críptica sintaxis de la expresión regular sea más confusa. Por ejemplo, supongamos que desea hacer coincidir una fecha. Dado que la posición del día y el mes se intercambia en algunas regiones, no está claro qué grupo se refiere al mes y qué grupo se refiere al día:

     

    const re = /(d{4})-(d{2})-(d{2})/;const match = re.exec('2020-03-04');console.log(match[0]); // → 2020-03-04console.log(match[1]); // → 2020console.log(match[2]); // → 03console.log(match[3]); // → 04

    La solución de ES2018 a este problema se denomina grupos de captura, que utilizan una sintaxis más expresiva en forma de (?name...):

    const re = /(?yeard{4})-(?monthd{2})-(?dayd{2})/;const match = re.exec('2020-03-04');console.log(match.groups); // → {year: "2020", month: "03", day: "04"}console.log(match.groups.year); // → 2020console.log(match.groups.month); // → 03console.log(match.groups.day); // → 04

    Debido a que el objeto resultante puede contener una propiedad con el mismo nombre que un grupo con nombre, todos los grupos con nombre se definen en un objeto separado llamado groups.

    Existe una construcción similar en muchos lenguajes de programación nuevos y tradicionales. Python, por ejemplo, usa la (?Pname)sintaxis para grupos con nombre. No es sorprendente que Perl admita grupos con nombres con sintaxis idéntica a JavaScript (JavaScript ha imitado su sintaxis de expresión regular de Perl). Java también utiliza la misma sintaxis que Perl.

    Además de poder acceder a un grupo con nombre a través del groupsobjeto, puede acceder a un grupo utilizando una referencia numerada, similar a un grupo de captura normal:

    const re = /(?yeard{4})-(?monthd{2})-(?dayd{2})/;const match = re.exec('2020-03-04');console.log(match[0]); // → 2020-03-04console.log(match[1]); // → 2020console.log(match[2]); // → 03console.log(match[3]); // → 04

    La nueva sintaxis también funciona bien con la asignación de desestructuración: Viajes y turismo

    const re = /(?yeard{4})-(?monthd{2})-(?dayd{2})/;const [match, year, month, day] = re.exec('2020-03-04');console.log(match); // → 2020-03-04console.log(year); // → 2020console.log(month); // → 03console.log(day); // → 04

    El groupsobjeto siempre se crea, incluso si no existe ningún grupo con nombre en una expresión regular:

    const re = /d+/;const match = re.exec('123');console.log('groups' in match); // → true

    Si un grupo con nombre opcional no participa en la coincidencia, el groupsobjeto seguirá teniendo una propiedad para ese grupo con nombre, pero la propiedad tendrá un valor de undefined:

    const re = /d+(?ordinalst|nd|rd|th)?/;let match = re.exec('2nd');console.log('ordinal' in match.groups); // → trueconsole.log(match.groups.ordinal); // → ndmatch = re.exec('2');console.log('ordinal' in match.groups); // → trueconsole.log(match.groups.ordinal); // → undefined

    Puede hacer referencia a un grupo capturado normal más adelante en el patrón con una referencia retrospectiva en forma de 1. Por ejemplo, el siguiente código utiliza un grupo de captura que coincide con dos letras seguidas y luego lo recupera más adelante en el patrón:

     

    console.log(/(ww)1/.test('abab')); // → true// if the last two letters are not the same // as the first two, the match will failconsole.log(/(ww)1/.test('abcd')); // → false

    Para recuperar un grupo de captura con nombre más adelante en el patrón, puede utilizar la /kname/sintaxis. Aquí hay un ejemplo:

    const re = /b(?dupw+)s+kdupb/;const match = re.exec("I'm not lazy, I'm on on energy saving mode"); console.log(match.index); // → 18console.log(match[0]); // → on on

    Esta expresión regular busca palabras duplicadas consecutivas en una oración. Si lo prefiere, también puede recuperar un grupo de captura con nombre utilizando una referencia anterior numerada:

    const re = /b(?dupw+)s+1b/;const match = re.exec("I'm not lazy, I'm on on energy saving mode"); console.log(match.index); // → 18console.log(match[0]); // → on on 

    También es posible utilizar una referencia anterior numerada y una referencia anterior nombrada al mismo tiempo:

    const re = /(?digitd):1:kdigit/;const match = re.exec('5:5:5'); console.log(match[0]); // → 5:5:5

    De manera similar a los grupos de captura numerados, los grupos de captura con nombre se pueden insertar en el valor de reemplazo del replace()método. Para hacer eso, necesitarás usar la $nameconstrucción. Por ejemplo:

    const str = 'War Peace';console.log(str.replace(/(War) (Peace)/, '$2 $1')); // → Peace Warconsole.log(str.replace(/(?WarWar) (?PeacePeace)/, '$Peace $War')); // → Peace War

    Si desea utilizar una función para realizar el reemplazo, puede hacer referencia a los grupos nombrados de la misma manera que haría referencia a los grupos numerados. El valor del primer grupo de captura estará disponible como segundo argumento de la función, y el valor del segundo grupo de captura estará disponible como tercer argumento:

    const str = 'War Peace';const result = str.replace(/(?WarWar) (?PeacePeace)/, function(match, group1, group2, offset, string) { return group2 + ' ' + group1;});console.log(result); // → Peace War

    s( dotAll) Bandera

    De forma predeterminada, el .metacarácter punto ( ) en un patrón de expresiones regulares
    coincide con cualquier carácter con la excepción de los caracteres de salto de línea, incluido el avance de línea ( n) y el retorno de carro ( r):

    console.log(/./.test('n')); // → falseconsole.log(/./.test('r')); // → false

    A pesar de esta deficiencia, los desarrolladores de JavaScript aún podrían hacer coincidir todos los caracteres mediante el uso de dos clases de caracteres abreviados opuestas como [wW], que indica al motor de expresiones regulares que haga coincidir un carácter que sea un carácter de palabra ( w) o un carácter que no sea una palabra ( W):

    console.log(/[wW]/.test('n')); // → trueconsole.log(/[wW]/.test('r')); // → true

    ES2018 tiene como objetivo solucionar este problema introduciendo el indicador s( dotAll). Cuando se establece este indicador, cambia el comportamiento del .metacarácter punto ( ) para que coincida también con los caracteres de salto de línea:

     

    console.log(/./s.test('n')); // → trueconsole.log(/./s.test('r')); // → true

    La sbandera se puede usar por expresión regular y, por lo tanto, no rompe los patrones existentes que dependen del comportamiento anterior del metacarácter de punto. Además de JavaScript, la sbandera está disponible en otros lenguajes como Perl y PHP.

    Lectura recomendada : Introducción resumida de dibujos animados a WebAssembly

    Escapes de propiedad Unicode

    Entre las nuevas características introducidas en ES2015 se encuentra el reconocimiento de Unicode. Sin embargo, las clases de caracteres taquigráficos aún no podían coincidir con los caracteres Unicode, incluso si use establecía la bandera.

    Considere el siguiente ejemplo:

    const str = ' ';console.log(/d/.test(str)); // → falseconsole.log(/d/u.test(str)); // → false

    se considera un dígito, pero dsolo puede coincidir con ASCII [0-9], por lo que el test()método devuelve false. Debido a que cambiar el comportamiento de las clases de caracteres taquigráficos rompería los patrones de expresión regulares existentes, se decidió introducir un nuevo tipo de secuencia de escape.

    En ES2018, los escapes de propiedades Unicode, indicados por p{...}, están disponibles en expresiones regulares cuando use establece la bandera. Ahora, para hacer coincidir cualquier número Unicode, simplemente puede usar p{Number}, como se muestra a continuación:

    const str = ' ';console.log(/p{Number}/u.test(str)); // → true

    Y para hacer coincidir cualquier carácter alfabético Unicode, puedes usar p{Alphabetic}:

    const str = '漢';console.log(/p{Alphabetic}/u.test(str)); // → true// the w shorthand cannot match 漢console.log(/w/u.test(str)); // → false

    P{...}es la versión negada p{...}y coincide con cualquier carácter que p{...}no:

    console.log(/P{Number}/u.test(' ')); // → falseconsole.log(/P{Number}/u.test('漢')); // → trueconsole.log(/P{Alphabetic}/u.test(' ')); // → trueconsole.log(/P{Alphabetic}/u.test('漢')); // → false

    Una lista completa de propiedades admitidas está disponible en la propuesta de especificación actual .

    Tenga en cuenta que el uso de una propiedad no admitida provoca SyntaxError:

    console.log(/p{undefined}/u.test('漢')); // → SyntaxError

    Tabla de compatibilidad

    Cromo Firefox Safari Borde
    Afirmaciones retrospectivas 62 X X X
    Grupos de captura con nombre 64 X 11.1 X
    s( dotAll) Bandera 62 X 11.1 X
    Escapes de propiedad Unicode 64 X 11.1 X
    ChromePara Android FirefoxPara Android Safari en iOS Borde móvil internet samsung Vista web de Android
    Afirmaciones retrospectivas 62 X X X 8.2 62
    Grupos de captura con nombre 64 X 11.3 X X 64
    s( dotAll) Bandera 62 X 11.3 X 8.2 62
    Escapes de propiedad Unicode 64 X 11.3 X X 64

    Nodo.js

    • 8.3.0 (requiere --harmonyindicador de tiempo de ejecución)
    • 8.10.0 (soporte para s( dotAll) bandera y aserciones de búsqueda hacia atrás)
    • 10.0.0 (soporte total)

    Terminando

    ES2018 continúa el trabajo de ediciones anteriores de ECMAScript al hacer que las expresiones regulares sean más útiles. Las nuevas características incluyen aserción retrospectiva, grupos de captura con nombre, indicador s( dotAll) y escapes de propiedades Unicode. La aserción de búsqueda hacia atrás le permite hacer coincidir un patrón solo si está precedido por otro patrón. Los grupos de captura con nombre utilizan una sintaxis más expresiva en comparación con los grupos de captura normales. El indicador s( dotAll) cambia el comportamiento del .metacarácter punto ( ) para que coincida con los caracteres de salto de línea. Finalmente, los escapes de propiedades Unicode proporcionan un nuevo tipo de secuencia de escape en expresiones regulares.

     

    Al crear patrones complicados, suele resultar útil utilizar un probador de expresiones regulares. Un buen probador proporciona una interfaz para probar una expresión regular frente a una cadena y muestra cada paso dado por el motor, lo que puede resultar especialmente útil cuando se intenta comprender patrones escritos por otros. También puede detectar errores de sintaxis que pueden ocurrir dentro de su patrón de expresiones regulares. Regex101 y RegexBuddy son dos probadores de expresiones regulares populares que vale la pena consultar.

    ¿Tiene alguna otra herramienta para recomendar? ¡Compártelos en los comentarios!

    (dm, il)Explora más en

    • javascript
    • Navegadores





    Tal vez te puede interesar:

    1. ¿Deberían abrirse los enlaces en ventanas nuevas?
    2. 24 excelentes tutoriales de AJAX
    3. 70 técnicas nuevas y útiles de AJAX y JavaScript
    4. Más de 45 excelentes recursos y repositorios de fragmentos de código

    Nuevas funciones de JavaScript que cambiarán la forma de escribir expresiones regulares

    Nuevas funciones de JavaScript que cambiarán la forma de escribir expresiones regulares

    Afirmaciones retrospectivasGrupos de captura con nombres( dotAll) BanderaEscapes de propiedad UnicodeTabla de compatibilidadTerminandoPatrones de diseño de in

    programar

    es

    https://pseint.es/static/images/programar-nuevas-funciones-de-javascript-que-cambiaran-la-forma-de-escribir-expresiones-regulares-967-0.jpg

    2024-05-20

     

    Nuevas funciones de JavaScript que cambiarán la forma de escribir expresiones regulares
    Nuevas funciones de JavaScript que cambiarán la forma de escribir expresiones regulares

    Si crees que alguno de los contenidos (texto, imagenes o multimedia) en esta página infringe tus derechos relativos a propiedad intelectual, marcas registradas o cualquier otro de tus derechos, por favor ponte en contacto con nosotros en el mail [email protected] y retiraremos este contenido inmediatamente

     

     

    Update cookies preferences