javascript - RegExp fungerar inte på läst HTML-fil


För det första vet jag hur de flesta RegExp-frågor går; och detta är inte en av de där "snälla skriv min kod"-frågorna.

Min förvirring ligger i det faktum att min RegExp fungerar på regexr, och i Chromes utvecklarverktyg när jag hämtar document.body.textContent, men inte på en HTML-fil efter att jag har läst in den i io.js.

io.js är version 1.5.1, kör på Windows 8

Varför skulle det fungera på båda platserna som anges, men inte i io.js? Tar jag inte hänsyn till något som io.js gör för att läsa filer?

Min RegExp borde matcha "@{each ___->___} text och radbrytningar @{/each}" precis som det gör i länken nedan, men istället returnerar den null

Här är vad jag försöker använda: http://regexr.com/3aldk

RegExp :

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

JS (Exempel):

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>

Missar jag något uppenbart, som en karaktär, som finns på baksidan men aldrig har tjänat?

Svar #1

Problemet här ligger på den fina linjen mellan specifikation och implementeringar.

ECMAscript 5.1-specifikationen anger att:

Ett --tecken kan behandlas bokstavligt eller det kan beteckna ett intervall. Det behandlas bokstavligt om det är det första eller sista tecknet i ClassRanges, början eller slutet av en intervallangivelse, eller om det följer omedelbart efter en intervallangivelse.

Regular-Expressions.info noterar att:

Bindestreck på andra positioner i teckenklasser där de inte kan bilda ett intervall kan tolkas som bokstavliga tecken eller som fel. Regex-varianter är ganska inkonsekventa om detta.

Slutsatser :

Det säkra sättet att inkludera ett bindestreck - minus-tecken i en teckenklass är genom att antingen:

  • escape det (t.ex. [a-zA-Z0-9\->.])
  • placera det som det första tecknet i klassen (t.ex. [-.>a-zA-Z0-9])

    • undantag: i en negaterad klass går det som andra, direkt efter ^ (t.ex. [^-.>a-zA-Z0-9])
  • placera det sist i klassen (t.ex. [a-zA-Z0-9.>-])

Allmänna kodningsriktlinjer föreslår att du placerar dina intervall först och avslutar teckenklassen med bindestrecket, detta undviker tvetydighet och förbättrar läsbarheten.

Sammanfattningsvis bör din RegEx bli:

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

Som ett extra tips:

du kan också skriva om [\s\S] (vilket blankstecken som helst eller vilket icke-blankstecken som helst) till [^] (inte ingenting)

vilket skulle sluta med följande RegEx:

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

JavaScript ... behandlar [^] som en negerad tom teckenklass som matchar vilket enskilt tecken som helst. - källa