Már ismered az alapokat: a \d és [A-Z] típusú karakterosztályokat, a {4} és + kvantifikátorokat, valamint a matches?, all-matching-subseqs és re-replace szavakat. Ez a feladat a reguláris kifejezések azon részeit mutatja be, amelyek a szerkezetet és a kontextust írják le. Ezek ugyanabban a regexp szókészletben élnek, ugyanazzal az R/ / literállal írva.
A horgonyok pozícióra illeszkednek, nem karakterre:
^ ! the start of the string
$ ! the end of the string
\b ! a word boundary
Mivel a $ a string végét jelenti, írd a \$-t, ha szó szerinti dollárjelre gondolsz.
A szóhatár (\b) az a pont, ahol egy szókarakter találkozik egy nem szókarakterrel. Szókarakternek számítanak a betűk, a számjegyek és az aláhúzásjel; minden más (szóközök, írásjelek és a string két vége) szóhatárnak számít. Így a \bcat\b csak akkor illeszkedik a cat-re, ha az önmagában áll:
USING: regexp ;
"cat nap" R/ \bcat\b/ re-contains? . ! => t
"scatter" R/ \bcat\b/ re-contains? . ! => f (cat sits inside a word)
A kerek zárójelek ( ) a minta egy részét csoportosítják, hogy egy kvantifikátor (vagy egy |, azaz „ez vagy az”) az egész csoportra vonatkozzon:
USING: regexp ;
"abab" R/ (ab)+/ matches? . ! => t (+ applies to "ab")
"dog" R/ cat|dog/ matches? . ! => t (either word)
"$100.50" R/ \$\d+(\.\d{2})?/ matches? . ! => t
"$100" R/ \$\d+(\.\d{2})?/ matches? . ! => t (the group is optional)
Az utolsó minta így olvasható: „dollárjel, egy vagy több számjegy, majd egy opcionális csoport, amely egy pontból és két számjegyből áll”.
Megjegyzés: a Factorban a csoport csak tagolja a mintát. Néhány regex-eszköztől eltérően nem tudod visszafejteni azt a szöveget, amelyre a csoport illeszkedett: nincs mód elfogó csoport kinyerésére, és a
\1-hez hasonló visszahivatkozások sem támogatottak. Ha egy támpont körüli szöveget szeretnél kiemelni, használj helyette lookaroundot (lásd lent).
A lookaround azt ellenőrzi, hogy mi áll közvetlenül az aktuális hely előtt vagy után, anélkül hogy ezeket a karaktereket a találat részévé tenné. „Nulla szélességű”: amit vizsgál, nem kerül bele az eredménybe.
(?=...) ! lookahead: ... must follow
(?!...) ! negative lookahead: ... must NOT follow
(?<=...) ! lookbehind: ... must come before
(?<!...) ! negative lookbehind: ... must NOT come before
A lookaround válogatós: ugyanazok a karakterek hol illeszkednek, hol nem, attól függően, hogy mi áll mellettük. Egy sima \d+ minden számot elkap; a lookbehind és a lookahead viszont csak azokat tartja meg, amelyeknek a megfelelő szomszédjuk van:
USING: regexp ;
"3 for $10 or 10 for $30" R/ \d+/ all-matching-subseqs .
! => { "3" "10" "10" "30" } (every number)
"3 for $10 or 10 for $30" R/ (?<=\$)\d+/ all-matching-subseqs .
! => { "10" "30" } (only the prices — the bare 3 and 10 drop)
"buy 2 at 15% off, 4 at 30% off" R/ \d+(?=%)/ all-matching-subseqs .
! => { "15" "30" } (only the discounts — the bare 2 and 4 drop)
Ha a záró / után egy betűt írsz, az megváltoztatja az egész minta viselkedését. Az i kis- és nagybetűtől függetlenné teszi az illesztést:
USING: regexp ;
"REFUND" R/ refund/i matches? . ! => t
"Refund" R/ refund/i matches? . ! => t
Az all-matching-subseqs átadja neked az illeszkedő szöveget. A map-matches egy lépéssel továbbmegy: lefuttat egy quotationt minden találatra, és összegyűjti az eredményeket. A quotation megkapja a találat start indexét, az end indexét és a teljes stringet; a subseq ebből a háromból állítja elő az illeszkedő szöveget, amelyet aztán átalakítasz:
map-matches ( string regexp quot: ( start end string -- obj ) -- seq )
USING: math regexp sequences ;
"a1 b22 c333" R/ \d+/ [ subseq length ] map-matches .
! => { 1 2 3 } (the length of each run of digits)
A pusztán mellékhatásokra szolgáló rokona, az each-match, minden találatra lefuttat egy quotationt, de semmit sem gyűjt össze.
Egy kisvállalat könyvelését vezeted, és a napi tranzakciók rendezetlen szövegsorként érkeznek. Reguláris kifejezésekkel fogod ellenőrizni az összegeket, kinyerni a számokat a jelölő szimbólumuk alapján, és megjelölni azokat a sorokat, amelyekre érdemes közelebbről is ránézni.
Egy szabályosan megírt összeg egy $ jelből, egy vagy több számjegyből, valamint egy opcionális tizedes részből áll, ami egy pontból és pontosan két számjegyből áll: $100 vagy $100.50, de a $100.5 nem az. Definiáld a valid-amount? függvényt, amely t-t ad vissza, ha a teljes string szabályosan megírt összeg.
"$100.50" valid-amount? . ! => t
"$100" valid-amount? . ! => t
"$100.5" valid-amount? . ! => f
Definiáld a dollar-amounts függvényt, amely minden olyan számot visszaad sorrendben, amely közvetlenül egy $ után áll a sorban, csak a számjegyeket, a $ nélkül.
"spent $100 and $25 today" dollar-amounts .
! => { "100" "25" }
Definiáld a percentages függvényt, amely minden olyan számot visszaad, amelyet közvetlenül egy % követ.
"up 5% then down 12%" percentages .
! => { "5" "12" }
Definiáld a flagged? függvényt, amely t-t ad vissza, ha a sorban a refund vagy a chargeback szó szerepel, bármilyen kis- és nagybetű-keveredésben.
"Issued a REFUND today" flagged? . ! => t
"a normal sale" flagged? . ! => f
Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) Factor nyelvet 47 fogalom163 feladat segítségével, valódi emberi mentorálással, mindez ingyen.