Hvernig svigar grípa hluta úr texta, hvernig endurraða má texta, og hvernig sama mynstur er notað í R og Python.
Hópar og endurnotkun
Svigar gera tvennt:
þeir hópa hluta af mynstri,
þeir geta gripið textann sem fannst.
Dæmi: línur á sniðinu nafn, netfang.
^(.+),\s*(.+@.+)$
Bútur
Merking
^
byrjun línu
(.+)
fyrsti hópur: nafn
,
komma
\s*
núll eða fleiri bil
(.+@.+)
einföld hugmynd um netfang
$
endir línu
Hóparnir gera okkur kleift að endurraða texta. Ef línan er:
Helga, helga@hi.is
má breyta henni í:
helga@hi.is Helga
með því að vísa í hóp 2 og svo hóp 1.
AthugasemdEinfalt fyrst, strangt seinna
Það er oft skynsamlegt að byrja á einföldu mynstri sem finnur líkleg tilvik, skoða niðurstöðuna, og herða svo mynstrið. Fullkomið netfangaregex er langt og ólærdómsríkt; fyrir gagnahreinsun er oft betra að nota nógu gott mynstur og skoða undantekningarnar.
Í R og Python
Sama mynstur má nota í mörgum málum. Hér er einfalt dæmi sem finnur netföng í texta.
txt <-c("Hafðu samband við helga@hi.is","Þetta er ekki netfang","Prófun: nemandi.1@example.org")mynstur <-"[\\w._%+-]+@[\\w.-]+\\.[A-Za-z]{2,}"fundid <-gregexpr(mynstur, txt, perl =TRUE)regmatches(txt, fundid)
R hefur tvær regex-vélar. Sú sjálfgefna er POSIX og þekkir ekki \w, \d né \s. Slepptu perl = TRUE og mynstrið hér að ofan skilar character(0) fyrir allar línurnar — engin villa, engin viðvörun, bara tómt svar.
Þetta er sérstaklega lúmskt þegar mynstur er afritað úr Python eða af regex101, því þar eru \w og \d sjálfsögð.
Tveir kostir í boði:
# 1) kveikja á PCRE-vélinniregmatches(txt, gregexpr("[\\w.]+@[\\w.-]+", txt, perl =TRUE))
Sömu föll taka perl = TRUE: grepl(), sub(), gsub(), regexpr().
import retxt = ["Hafðu samband við helga@hi.is","Þetta er ekki netfang","Prófun: nemandi.1@example.org",]for lina in txt:print(re.findall(r"[\w._%+-]+@[\w.-]+\.[A-Za-z]{2,}", lina))
['helga@hi.is']
[]
['nemandi.1@example.org']
Taktu eftir að í R þarf oft að tvöfalda bakskástrik í strengjum: \\d í R-streng verður \d í regex. Í Python er algengt að nota hráa strengi með r"...", þá þarf síður að tvöfalda bakskástrik.
MikilvægtFyrsta samsvörun eða allar?
Mynstur getur passað víða í sama texta. Föllin skiptast í tvennt: sum skila fyrstu samsvörun frá vinstri, önnur skila öllum.
pantanir <-"Pantanir: 12, 345 og 6789"# fyrsta samsvörunregmatches(pantanir, regexpr("\\d+", pantanir, perl =TRUE))
[1] "12"
# allar samsvaranirregmatches(pantanir, gregexpr("\\d+", pantanir, perl =TRUE))
[[1]]
[1] "12" "345" "6789"
import repantanir ="Pantanir: 12, 345 og 6789"print(re.search(r"\d+", pantanir).group()) # fyrsta samsvörun
12
print(re.findall(r"\d+", pantanir)) # allar samsvaranir
['12', '345', '6789']
Innan hverrar samsvörunar er +gráðugt: það tekur eins marga tölustafi og það kemst upp með í röð, en stoppar á fyrsta stafnum sem passar ekki. Þá er \d+ á 588-5522 ekki allt símanúmerið heldur bara 588 — bandstrikið er ekki tölustafur. Ef númerið allt á að fylgja þarf mynstrið að segja það: \d{3}-\d{4}.
Þetta skiptir máli þegar ein tala á að fara í töflu: fyrsta samsvörun er ekki endilega sú sem þú ætlaðir að lesa. Skoðaðu alltaf allar samsvaranir áður en þú velur eina.
Finndu öll símanúmer, hvort sem þau eru skrifuð 5551234, 555-1234 eða 555 1234.
Breyttu símanúmerunum yfir í samræmt snið: 555-1234.
Hver af línunum ætti ekki að fara inn í hreina tengiliðatöflu? Af hverju?
Mynstur til að byrja með:
[\w._%+-]+@[\w.-]+\.[A-Za-z]{2,}
\d{3}[- ]?\d{4}
Markmiðið er ekki að skrifa fullkomið regex í fyrstu tilraun. Markmiðið er að geta lesið mynstrið, prófað það, séð hvað það finnur ranglega og lagað það meðvitað.
ÁbendingPrófaðu fyrst utan kóða
Settu textann og mynstrin inn á regex101 áður en þú skrifar lausnina í R eða Python. Skráðu hjá þér eitt dæmi sem passar rétt og eitt dæmi sem mynstrið finnur ekki eða finnur ranglega.