Eroja regexp-kirjastoissa



Regexp-kirjastot ovat funktionaalisesti kaikki samanlaisia. Vai ovatko?

Eivät sittenkään. Osassa on mietitty vähän hämärämpiä käyttötapauksia, ja mahdollistettu muun muassa osittaisen matchin erottaminen epäonnistuneesta matchista. Kaikkein yleisikäyttöisin rajapinta olisi sellainen, joka mahdollistaisi täyden streamauksen, mutta se on harvinainen.

Otetaan esimerkki käyttötapauksesta: webissä on sivu, ja sivulla lomake, jossa on kenttiä, joilla on jotain muotovaatimuksia. Kehittäjä määrittelee muotovaatimuksen regexpillä. Halutaan dynaamisesti päivittyvä feedback, joka osaa kertoa, ei pelkästään onko kenttään kirjoitettu data kelvollista tai kelvotonta, vaan myös että voisiko se olla kelvollista, jos siihen lisättäisiin vielä jotain. Näin esim. luottokorttinumero olisi kesken kirjoittamisensa tilassa “ei vielä ok, mutta jos kirjoitat lisää, voisi olla ok”.

Tämän toteuttaminen pelkällä regexpin match-metodilla on hieman hankalaa. Aidoille regexpeille voidaan toteuttaa automaattinen transformaatio, joka muuttaa yhden regexpin toiseksi, joka matchaa kaikkiin ensimmäisen valideihin prefikseihin. Jos regexpejä laajennetaan epäaidoiksi sallimalla back referencet, tämä strategia ei enää edes toimi.

PCRE:ssä (C-kirjasto) erottelu saadaan aikaan antamassa pcre_exec:ille flageissa PRCE_PARTIAL_HARD, ja tunnistamalla paluuarvona PCRE_ERROR_PARTIAL (vastakohtana PCRE_ERROR_NOMATCH:ille). (Englanninkielinen termi on partial match.)

Muita tutkiessa vastaan tulleita kirjastoja, joissa tämä onnistuu, on Boost (C++) ja JRegex (Java). Boostia voi pitää jossain määrin standardina C++-ympyröissä. Javassa useimmat ammatinharjoittajat käyttävät standardikirjaston regexpejä, eikä tule mieleenkään, että parempikin ratkaisu (ja kyllä, JRegex on monilla tavoin parempi) on olemassa.

Pythonin standardikirjasto ei tätä tue, eikä laajennustakaan löydetty. Samoin kävi Javascriptin tapauksessa.

Oikeastaan ainoa asia, joka jäi enemmän häiritsemään, oli Javascript. Alkuperäinen käyttötapaushan haluttaisiin tietysti toteuttaa Javascriptillä, koska kyseessä on selaimessa tehtävä tarkistus.

Jos tarinassa on mitään varsinaista opetusta, se on se, että sen jälkeen, kun joku ominaisuus on saavuttanut kielen standardikirjaston, viat, jotka siihen ovat jääneet, ovat ikuisia. Vaikka ne korjattaisiinkin laajennukseen, suurin osa kehittäjistä käyttää standardikirjastoa. Tämä ei tietenkään koske suoranaisia bugeja toteutuksessa, koska ne on helppo korjata, vaan tällaisia korkeamman tason ajatusvirheitä siitä, mikä on mahdollisten käyttötapausten kenttä.

Niin, se täysi streamaus: kuvitellaan tilanne, jossa matchattava sisältö on pitkää, syöte tulee streamista ja tulos menee streamiin. Tällöin olisi hyötyä regexp-matcherista, jolle syöte voidaan antaa mielivaltainen pala kerrallaan, ja joka aina palan jälkeen osaa sanoa, missä tilassa on. Nämä tilat ovat no match, match ja ei voida tietää vielä, eli osittainen match.

Yleiskäyttöisiä palikoita suunnitellessa on aina ristivetoa streamattavien rajapintojen laajemman käytettävyyden ja kerralla asiat tekevien rajapintojen implementoinnin helppouden välillä. Aina oikeaa valintaa ei ole.

Tämän artikkelin on kirjoittanut Teemu Kalvas ja sitä ovat sittemmin muokanneet muut Codenton työntekijät.

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *