Regulaaravaldised
Paljud erinevad ülesanded on seotud tekstist mingi seaduspärasusele vastava info leidmisega. Näiteks on ülesandeks leida ette antud tekstist kõik meiliaadressid. Regulaaravaldis on formaalne viis tekstis leiduva mustri kirja panemiseks. Mustriks võib näiteks meiliaadress või telefoninumber.
Pythonis on regulaaravaldistega töötamiseks tehtud moodul re
.
Järgnevas näites otsime sõnest "an example word:cat!!!" üles alamsõne, mis vastab regulaaravaldisele word:\w\w\w
.
Regulaaravaldisele vastab täpne sõne "word:" ning sellele järgnevad 3 suvalist tähte.
Meetod re.search(pattern, text)
tagastab otsingu õnnestumisel match
objekti koos leitud alamsõnega vastasel juhul tagastatakse None
.
import re
text = 'an example word:cat!!'
pattern = r'word:\w\w\w'
match = re.search(pattern, text)
# If-statement after search() tests if it succeeded
if match:
print('found', match.group()) ## 'found word:cat'
else:
print('did not find')
match = re.search(pattern, text)
salvestab otsingu tulemuse muutujasse match
.
if match not None
(ehk if match
) kontrollib, kas otsing õnnestus.
match.group()
tagastab leitud teksti ("word:cat").
r"string"
on "raw" tüüpi string, mis tähendab, et kurakaldkriipsud("\"
) jäetakse teksti alles.
Nii on mugavam regulaaravaldisi kirja panna, kuna regulaaravaldistes kasutatakse mustrite kirjapanemiseks kurakaldkriipse.
Näide:
- raw string
r'word:\w\w\w'
- regular string
'word:\\w\\w\\w'
Süntaks
Tabel annab lühiülevaate regulaaravaldise süntaksist. Täpsemalt võib vaadata näiteks siit
Muster |
info |
Näide |
Tekst (kust otsitakse) |
|
---|---|---|---|---|
Leiab |
Ei leia |
|||
täht ise |
info |
"abc" |
"abc" |
"aba" |
. |
suvaline sümbol |
"a.bc" |
"a#bc" |
"abc" |
^ |
algus |
"^abc" |
"abcde" |
"dabc" |
$ |
lõpp |
"abc$" |
"dabc" |
"abcd" |
? |
0 või üks kord |
"ab?c" |
"ac" "abc" |
"abbc" |
* |
0 või rohkem |
"ab*c" |
"ac" "abc" "abbc" |
"ccbbaa" |
+ |
1 või rohkem |
"ab+c" |
"abc" "abbc" |
"accbcc" "ac" |
{m} |
kordub m korda |
"ab{2}c" |
"aabbcc" "abbc" |
"abc" "abbbc" |
{m, n} |
kordub m kuni n korda |
"ab+{2,3}c" |
"abbcc" "abbbcc" |
"aabbbbcc" "abc" |
\ |
escape Et kasutada regex erisümboleid otseses tähenduses, näiteks, et "." tähistaks punkti, mitte suvalist tähte |
"ab\.c" |
"ab.c" |
"ab#c" |
[..] |
sobiv hulk hulk, millest otsida |
"[ab]cd" |
"acd" "bcd" |
"ccdc" "cd" |
[..-..] |
sobiv vahemik hulk, millest otsida |
"[a-d]ef" |
"aef" "def" |
"ef" "abc" |
[..\-] |
miinus hulgas |
"[a\-d]ef" |
"def" "-ef" |
"ef-" "cef" |
(..) |
grupeerimine |
"(ab)?cd" |
"cd", "acde" "abcde", "abbcd" |
"ab" "abc" |
| |
või |
"(ab|cd)+ef" |
"abefg", "cdefg" "ababef", "cdcdef" |
"acef", "efg" "aef", "def" |
\1, \2 |
1., 2. sulu kattumine |
"(.+) \1" |
"a a", "11 12", "55 55", |
"aa", "11 21" |
\w |
tähed, numbrid, alakriips |
"\w+" |
"abc" "1a" |
".,~@", " " |
\s |
tühik, tabulaator, reavahetus |
"a\sb" |
"a b" "a\tb" |
"ab", "ab" |
\d |
numbrid |
"\d+i" |
"23i" |
"i7" |
[^..] |
ei kuulu hulka |
"[^ab]+c" |
"ccc", "dec" |
"abc", "bbc" |
(?=...) |
positiivne lookahead |
"ab(?=cd)" |
"abcd", "abcda" |
"abdd", "abc" |
(?!...) |
negatiivne lookahead |
"ab(?!cd)" |
"abc", "abcccc" |
"oabcd", "abcdd" |
(?<=...) |
posiitvne lookbehind |
"(?<=cd)ok" |
"cdok", "ccdok" |
"cddok" |
(?<!...) |
negatiivne lookbehind |
"(?<!cd)ok" |
"cddok", "ok", "dok" |
"cdok", "ccdok" |
Harjutus
Regexi harjutamiseks proovi välja mõelda järgnevad mustrid:
Kirjuta selline
email_pattern
, et leida tekstist Toomase mailiaadress.Kirjuta selline
phone_pattern
, et leida tekstist Toomase telefoninumber.
import re
info_text = """
Toomas:
email: akadeemia-toomas@taltech.ee
phone: 5204 2456
"""
email_pattern = r'' # your pattern here
phone_pattern = r'' # your pattern here
email_match = re.search(email_pattern, info_text)
phone_match = re.search(phone_pattern, info_text)
email = email_match.group() if email_match else "NOT FOUND" # -> "akadeemia-toomas@taltech.ee"
phone = phone_match.group() if phone_match else "NOT FOUND" # -> "5204 2456"
print(email)
print(phone)
import re
info_text = """
Toomas:
email: akadeemia-toomas@taltech.ee
phone: 5204 2456
"""
email_pattern = r'[\w\-]+@\w+\.\w+'
phone_pattern = r'\d[\d\s]+\d'
email_match = re.search(email_pattern, info_text)
phone_match = re.search(phone_pattern, info_text)
email = email_match.group() if email_match else "NOT FOUND"
phone = phone_match.group() if phone_match else "NOT FOUND"
print(email)
print(phone)
test_object("email")
test_object("phone")
success_msg("Good job!")
Grupid
Regexiga saab otsingu tulemusi gruppideks jagada. Grupide jaoks peame osa regulaaravaldisest sulgude sisse panema.
Grupid on nummerdatud alates ühest. match.group(1)
tagastab meile esimese grupi.
Näiteks saab kuupäevi kujul "dd.MM.yyyy" otsida tekstist järgnevalt:
import re
date = "I was born on 05.12.1995."
pattern = r'(\d{1,2})\.(\d{1,2})\.(\d{1,4})'
match = re.search(pattern, date)
print("Full match: " + match.group(0)) # or match.group()
print("Day: " + match.group(1))
print("Month: " + match.group(2))
print("Year: " + match.group(3))
Mitme tulemuse leidmine
Kui tekstis on rohkem kui üks regulaaravaldisele vastav alamsõne saab kõikide vastete järjendi moodustada funktsiooniga
findall()
import re
text = "Minu email on foo-baz@bar.com, sõbra email on guido@baggins.com ja guits@bag.com"
pattern = r'' # write email pattern here
emails = re.findall(pattern, text)
for email in emails:
print(email)
import re
text = "Minu email on foo-baz@bar.com, sõbra email on guido@baggins.com ja guits@bag.com"
pattern = r'[\w\-]+@\w+\.\w+' # write email pattern here
emails = re.findall(pattern, text)
for email in emails:
print(email)
test_object("emails")
success_msg("Good job!")