javascript - RegExp ei toimi luetulla HTML-tiedostolla


Ensinnäkin tiedän, miten useimmat RegExp-kysymykset menevät; eikä tämä ole yksi niistä "kirjoita koodini puolestani" -kysymyksistä.

Hämmennykseni johtuu siitä, että minun RegExp toimii regexrissä ja Chromen kehittäjätyökaluissa, kun tarkastelen document.body.textContent -sisältöä, mutta ei HTML-tiedostossa sen jälkeen kun olen lukenut sen io.js:llä.

io.js on versio 1.5.1, toimii Windows 8:lla

Miksi se toimisi molemmissa luetelluissa paikoissa, mutta ei io.js:ssä? Enkö ota jotain huomioon, mitä io.js tekee tiedostojen lukemiseen?

Minun RegExp tulisi vastata "@{each ___->___} text and line breaks @{/each}" kuten alla olevassa linkissä, mutta sen sijaan se palauttaa null

Tässä on se, mitä yritän käyttää: http://regexr.com/3aldk

Säännöllinen lauseke :

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

JS (Esimerkki):

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>

Puuttuuko minulta jokin ilmeinen, kuten merkki, joka on takapuolella, mutta ei ole koskaan palvellut?

Vastaus #1

Ongelma tässä piilee hienovaraisella rajalla määrityksen ja toteutusten välillä.

ECMAscript 5.1 -määritelmä sanoo, että:

Merkkiä - voidaan käsitellä kirjaimellisesti tai se voi merkitä aluetta. Sitä käsitellään kirjaimellisesti, jos se on ClassRangesin ensimmäinen tai viimeinen merkki, alueen määrityksen alku- tai loppuraja, tai jos se seuraa välittömästi alueen määritystä.

Regular-Expressions.info huomauttaa, että:

Tavuviivat muissa sijainneissa merkkiluokissa, joissa ne eivät voi muodostaa aluetta, voidaan tulkita kirjaimina tai virheinä. Säännöllisen lausekkeen (regex) muodot ovat tässä melko epäyhtenäisiä.

Johtopäätökset :

Turvallinen tapa sisällyttää viiva - miinusmerkki merkkiluokkaan on jompikumpi seuraavista:

  • pakene siitä (esim. [a-zA-Z0-9\->.])
  • asettamalla se luokan ensimmäiseksi merkiksi (esim. [-.>a-zA-Z0-9])

    • poikkeus: kieltoluokassa se tulee toisena, heti ^-merkin jälkeen (esim. [^-.>a-zA-Z0-9])
  • asettamalla se viimeiseksi luokassa (esim. [a-zA-Z0-9.>-])

Yleiset koodausohjeet suosittelevat sijoittamaan jaksot ensin ja päättämään merkkiluokan väliviivaan, tämä välttää epäselvyyksiä ja auttaa luettavuutta.

Yhteenvetona, RegExisi tulisi olla:

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

Lisävinkkinä:

voit myös kirjoittaa uudelleen [\s\S] (mikä tahansa välilyöntimerkki tai mikä tahansa ei-välilyöntimerkki) muotoon [^] (ei mitään)

joka päätyisi sinut seuraavan RegExin kanssa:

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

JavaScript ... käsittelee [^] kuin käännettyä tyhjää merkki-luokkaa, joka vastaa mitä tahansa yksittäistä merkkiä. - lähde