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}/gJS (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])
- undantag: i en negaterad klass går det som andra, direkt efter
[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
