Búsqueda de sitios web

javascript - RegExp no funciona en archivo HTML leído


Antes que nada, sé cómo suelen ser la mayoría de las preguntas sobre RegExp; y esta no es una de esas preguntas de "por favor, escribe mi código".

Mi confusión radica en el hecho de que mi RegExp funciona en regexr, y en las herramientas de desarrollo de Chrome al examinar el document.body.textContent, pero no en un archivo HTML después de haberlo leído en io.js.

io.js es la versión 1.5.1, funcionando en Windows 8

¿Por qué funcionaría en ambos lugares mencionados, pero no en io.js? ¿Acaso no estoy tomando en cuenta algo que io.js hace para leer archivos?

Mi RegExp debería coincidir con "@{each ___->___} texto y saltos de línea @{/each}" como lo hace en el enlace a continuación, pero en cambio, devuelve null

Aquí está lo que estoy tratando de usar: http://regexr.com/3aldk

Expresión regular :

/@\{each ([a-zA-Z0-9->.]*)\}([\s\S]*)@\{\/each}/g

JS (Ejemplo):

fs.readFile('view.html', {encoding:'utf8'}, function(error, html) {
    console.log(html.match(myRegExp)); // null
});

HTML :

<!doctype html>
<html>
    <head>
        <title>@{title}</title>
    </head>
    <body>
        <h1>@{foo.bar}</h1>
        <p>
            Lorem ipsum dolor sit amet, @{foo.baz.hoo}
        </p>
        @{each people->person}
            <div>
                <b>@{person.name}:</b> @{person.age}
            </div>
        @{/each}
    </body>
</html>

¿Me estoy perdiendo algo obvio, como un personaje, que está presente en el reverso, pero que nunca ha servido?

Respuesta #1

El problema aquí radica en la delgada línea entre especificación y implementaciones.

La especificación ECMAscript 5.1 establece que:

Un carácter - puede tratarse de manera literal o puede denotar un rango. Se trata de manera literal si es el primer o último carácter de ClassRanges, el límite inicial o final de una especificación de rango, o si sigue inmediatamente a una especificación de rango.

Regular-Expressions.info señala que:

Los guiones en otras posiciones dentro de las clases de caracteres donde no pueden formar un rango pueden interpretarse como literales o como errores. Los sabores de expresiones regulares son bastante inconsistentes al respecto.

Conclusiones :

La manera segura de incluir un guion - signo menos en una clase de caracteres es mediante cualquiera de las siguientes:

  • escapándolo (por ejemplo, [a-zA-Z0-9\->.])
  • colocándolo como el primer carácter en la clase (por ejemplo, [-.>a-zA-Z0-9])

    • excepción: en una clase negada va en segundo lugar, justo después de ^ (ej. [^-.>a-zA-Z0-9])
  • colocándolo al final de la clase (por ejemplo, [a-zA-Z0-9.>-])

Las pautas generales de codificación sugieren colocar sus rangos primero y terminar la clase de caracteres con el guion, esto evita ambigüedades y ayuda a la legibilidad.

Resumiendo, tu RegEx debería convertirse en:

/@\{each ([a-zA-Z0-9>.-]*)\}([\s\S]*)@\{\/each}/g

Como un consejo adicional:

también podrías reescribir [\s\S] (cualquier carácter de espacio en blanco o cualquier carácter que no sea espacio en blanco) como [^] (no nada)

lo que te dejaría con la siguiente expresión regular:

/@\{each ([a-zA-Z0-9>.-]*)\}([^]*)@\{\/each}/g

JavaScript ... trata [^] como una clase de caracteres vacía negada que coincide con cualquier carácter individual. - fuente