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}/gJS (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])
- undtagelse: i en negéreret klasse kommer det som nr. 2, lige efter
[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
