javascript - RegExp virker ikke på læst HTML-fil


Først og fremmest ved jeg, hvordan de fleste RegExp-spørgsmål går; og dette er ikke et af de der "skriv venligst min kode"-spørgsmål.

Min forvirring ligger i det faktum, at min RegExp virker på regexr og i Chromes udviklerværktøjer, når jeg poller document.body.textContent, men ikke på en HTML-fil, efter at jeg har læst den ind i io.js.

io.js er version 1.5.1, kører på Windows 8

Hvorfor ville det fungere på begge de nævnte steder, men ikke i io.js? Tager jeg ikke noget i betragtning, som io.js gør for at læse filer?

Min RegExp skal matche "@{each ___->___} tekst og linjeskift @{/each}" som den gør i linket nedenfor, men i stedet returnerer den null

Her er, hvad jeg prøver at bruge: http://regexr.com/3aldk

RegExp :

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

JS (Eksempel):

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>

Mangler jeg noget indlysende, som en karakter, der er til stede på bagsiden, men aldrig er kommet frem?

Svar #1

Problemet her ligger på den fine linje mellem specifikation og implementeringer.

ECMAscript 5.1-specifikationen angiver, at:

Et - tegn kan behandles bogstaveligt, eller det kan angive et interval. Det behandles bogstaveligt, hvis det er det første eller sidste tegn i ClassRanges, begyndelsen eller slutningen af en intervalangivelse, eller umiddelbart følger efter en intervalangivelse.

Regular-Expressions.info bemærker, at:

Bindestreger på andre positioner i tegnklasser, hvor de ikke kan danne et interval, kan blive tolket som bogstavelige tegn eller som fejl. Regex-varianter er ret inkonsistente med hensyn til dette.

Konklusioner :

Den sikre måde at inkludere et bindestreg - minustegn i en tegnklasse på er enten ved:

  • at undslippe det (f.eks. [a-zA-Z0-9\->.])
  • placere det som det første tegn i klassen (fx [-.>a-zA-Z0-9])

    • undtagelse: i en negéreret klasse kommer det som nr. 2, lige efter ^ (f.eks. [^-.>a-zA-Z0-9])
  • placere det sidst i klassen (f.eks. [a-zA-Z0-9.>-])

Generelle kodningsretningslinjer foreslår at placere dine intervaller først og afslutte tegnklassen med bindestregen, dette undgår tvetydighed og hjælper læsbarheden.

Opsummerende bør din RegEx blive:

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

Som et ekstra tip:

du kunne også omskrive [\s\S] (ethvert mellemrumstegn eller ethvert ikke-mellemrumstegn) til [^] (ikke ingenting)

hvilket ville ende med, at du får følgende RegEx:

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

JavaScript ... behandler [^] som en negere tom tegnklasse, der matcher ethvert enkelt tegn. - kilde