Razvoj softvera za embedded operativne sisteme
1 / 50

Regularni izrazi

Regularni izrazi (regex) su specijalni tekstualni stringovi koji opisuju šablon za pretragu. Omogućavaju efikasnu pretragu, validaciju i ekstrakciju podataka iz tekstualnih izvora.

Moćan alat za programere i inženjere softvera
Koriste se u mnogim programskim jezicima i alatima
Učenje regex-a štedi vreme i povećava produktivnost
Osnove

Šta su regularni izrazi?

2 / 50

Regularni izrazi su specijalni tekstualni stringovi koji opisuju šablon za pretragu. Oni predstavljaju moćan i fleksibilan način da se definišu obrasci u tekstu, koji se mogu koristiti za pronalaženje, validaciju ili zamenu podataka. Regex može biti posmatran kao unapređena verzija wildcard karaktera, ali sa mnogo većom preciznošću i mogućnostima.

  • Koriste se za pretragu tekstualnih fajlova, validaciju korisničkog unosa, parsiranje podataka i još mnogo toga.
  • Podržani su u gotovo svim modernim programskim jezicima i alatima za obradu teksta.
  • Omogućavaju da se složeni obrasci opišu u jednoj liniji koda, što štedi vreme i smanjuje greške.
Primer
Wildcard: *.txt Regex: .*\.txt
Terminologija

Regex je skraćenica za regularni izraz, odnosno šablon koji opisuje određeni segment teksta.

Motivacija

Zašto su regex korisni?

3 / 50
Prednosti
  • Omogućavaju da se složena pravila opišu u jednoj liniji koda.
  • Štede vreme i smanjuju količinu koda potrebnog za obradu teksta.
  • Koriste se za validaciju ulaza, ekstrakciju podataka i zamenu teksta.
Podrška
  • Prisutni su u većini programskih jezika (Java, Python, PHP, JavaScript, .NET).
  • Koriste se u tekst editorima i alatima za pretragu i zamenu.
  • Popularni su u komandnim alatima poput grep, sed i awk.
Primer

Regex za email adresu

4 / 50
Regex
\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}\b
Opis
  • Početak granice reči \b osigurava da se poklapa cela email adresa.
  • Prvi deo opisuje korisničko ime (slova, cifre, tačke, donje crte, znakove +, - i %).
  • Zatim sledi znak @.
  • Drugi deo opisuje domen (slova, cifre, tačke i crtice).
  • Na kraju je ekstenzija domena od 2 do 4 slova.
Java primer

Validacija email adrese u Javi

5 / 50
Kod
public class JavaRegexExamples { public static final String VALID_EMAIL_ADDRESS = "t_pedja@uns.ac.rs"; public static final String INVALID_EMAIL_ADDRESS = "teodorovic.predrag@gmail.c0m"; private static void simpleMatch() { String regexPattern = "\\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}\\b"; System.out.print("Provera da li je " + VALID_EMAIL_ADDRESS + " validna email adresa: "); System.out.println(VALID_EMAIL_ADDRESS.matches(regexPattern) ? " jeste" : " nije"); System.out.print("Provera da li je " + INVALID_EMAIL_ADDRESS + " validna email adresa: "); System.out.println(INVALID_EMAIL_ADDRESS.matches(regexPattern) ? " jeste" : " nije"); } }
Rezultat

Izlaz programa

6 / 50
Izlaz
Provera da li je t_pedja@uns.ac.rs validna email adresa: jeste Provera da li je teodorovic.predrag@gmail.c0m validna email adresa: nije
Zaključak
  • Regex se može koristiti za proveru formata unosa.
  • Efikasno odvaja validne od nevalidnih primera.
Matcher / Pattern

Pronalaženje svih email adresa u tekstu

7 / 50
Kod
import java.util.regex.Matcher; import java.util.regex.Pattern; public class JavaRegexExamples { public static final String EMAIL_ADDRESS_TEST = "Moja fakultetska email adresa je t_pedja@uns.ac.rs, a privatna teodorovic.predrag@gmail.com."; public static void patternMatch() { String regexPattern = "\\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}\\b"; Pattern pattern = Pattern.compile(regexPattern); Matcher matcher = pattern.matcher(EMAIL_ADDRESS_TEST); while (matcher.find()) { System.out.print("Start index: " + matcher.start()); System.out.print(" End index: " + matcher.end() + " email adresa: "); System.out.println(matcher.group()); } } }
Rezultat

Izlaz pronalaženja email adresa

8 / 50
Izlaz
Start index: 33 End index: 50 email adresa: t_pedja@uns.ac.rs Start index: 63 End index: 91 email adresa: teodorovic.predrag@gmail.com
Napomena

Može se koristiti i Pattern.CASE_INSENSITIVE kada ne želimo da razlikujemo velika i mala slova.

Pojmovi

Terminologija

9 / 50
Osnovni termini
  • Regex = regularni izraz
  • Match = poklapanje
  • String = ulazni tekst
  • Regex engine = mehanizam za obradu regex-a
Napomena

Poklapanje označava deo teksta koji odgovara zadatom obrascu.

Najjednostavniji regex

Literali

10 / 50
Primeri
a cat
Objašnjenje
  • a poklapa prvo pojavljivanje znaka a
  • cat traži sekvencu c-a-t
  • Regexcatpoklapa "cat" u tekstu: "About cats and dogs"
  • Regex je podrazumevano case-sensitive
Metakarakteri

Specijalni karakteri

11 / 50
Lista
[ \ ^ $ . | ? * + ( )
Escape

Ako ih želimo koristiti kao obične karaktere, moramo ih escape-ovati znakom \.

1\+1=2
Specijalne sekvence

Karakteri koji se ne prikazuju

12 / 50
Sekvence
\t tab \r carriage return \n line feed \a bell \e escape \f form feed \v vertical tab
Napomena
  • Windows završava red sa \r\n
  • Linux koristi \n
Princip rada

Kako radi regex engine?

13 / 50
Pravilo

Leftmost Match First

  • Prvo poklapanje sa leve strane biće vraćeno.
  • Kasnije „bolje” poklapanje se ne traži.
Proces
  • Engine kreće od početka stringa.
  • Pokušava sve opcije na trenutnoj poziciji.
  • Ako ne uspe, pomera se na sledeći karakter.
Primer

Primer rada regex engine-a

14 / 50
Primer
Regex: cat String: He captured a catfish for his cat.
Zaključak

Prvo uspešno poklapanje je cat u reči catfish, jer regex engine vraća najlevlje poklapanje.

Skupovi

Klase karaktera

15 / 50
Primeri
[ae] [0-9] [A-Za-z_] [0-9a-fA-F]
Napomena
  • Klasa karaktera poklapa tačno jedan karakter.
  • Redosled karaktera u klasi nije važan.
Primena

Korisne primene klasa karaktera

16 / 50
Primeri
gr[ae]y sep[ae]r[ae]te li[cs]en[cs]e [A-Za-z_][A-Za-z_0-9]* 0[xX][A-Fa-f0-9]+
Negacija

Invertovane klase karaktera

17 / 50
Primer
[^0-9] q[^u]
Objašnjenje
  • [^0-9] poklapa sve osim cifre.
  • q[^u] znači q pa karakter koji nije u.
Detalj

Metakarakteri unutar klasa karaktera

18 / 50
Specijalni unutar []
] \ ^ -
Primeri
[+*] [\\x] [x^] []x] [-x] [x-]
Prečice

Skraćeno označavanje klasa karaktera

19 / 50
Osnovne skraćenice
\d -> cifra[0-9] \w -> karakter reči \s -> whitespace karakter
Primeri
\s\d [\s\d] [\da-fA-F]
Negirane prečice

Invertovano skraćeno označavanje

20 / 50
Negacije
\D \W \S
Važna razlika
[\D\S] != [^\d\s]

Prvi izraz praktično poklapa bilo koji karakter, dok drugi isključuje cifre i whitespace.

Ponavljanje

Ponavljanje klasa karaktera

21 / 50
Primeri
[0-9]+ ([0-9])\1+
Objašnjenje
  • [0-9]+ poklapa niz cifara.
  • ([0-9])\1+ poklapa isti karakter više puta, npr. 222.
Metakarakter .

Tačka poklapa (skoro) sve karaktere

22 / 50
Značenje

Tačka poklapa bilo koji karakter osim newline karaktera.

Ekvivalent
[^\n] [^\r\n]
Oprez

Koristite tačku pažljivo

23 / 50
Loš regex za datum
\d\d.\d\d.\d\d
Problem

Poklopiće i 02512703, što nije ono što želimo.

Poboljšanje

Bolji regex za datum

24 / 50
Primeri
\d\d[- /.]\d\d[- /.]\d\d [0-3]\d[- /.][0-1]\d[- /.]\d\d
Napomena

I dalje nije savršeno, ali je bolje od korišćenja tačke. Regex preciznije definiše dozvoljene separatore i opseg dana i meseca.

Bolja praksa

Koristite invertovanu klasu karaktera umesto tačke

25 / 50
Loše
".*"
Bolje
"[^"\r\n]*"
Objašnjenje

Regex sa tačkom i zvezdicom je pohlepan i može poklopiti previše teksta. Korišćenjem invertovane klase karaktera ograničavamo poklapanje samo na željene karaktere. Na tekstu "Houston" we have a "problem" ovaj regex će poklopiti upravo to: "Houston" we have a "problem", umesto pojedinačnih navodnika.

Pozicije

Markeri za početak i kraj stringa

26 / 50
Markeri
^ početak stringa $ kraj stringa
Primeri
^a poklapa a samo na početku stringa c$ poklapa c samo na kraju stringa
Praktično

Primer validacije celobrojnog podatka

27 / 50
Regex
^\d+$
Značenje
  • početak stringa
  • jedna ili više cifara
  • kraj stringa
  • Poklapa: 123
  • Poklapa: 987654
  • Ne poklapa:: 123a
  • Ne poklapa:: a123
Multiline

Korišćenje ^ i $ za linije

28 / 50
Multiline režim

U multiline režimu, ^ i $ mogu označavati početak i kraj svake linije, a ne samo celog stringa.

Specijalni markeri
\A početak stringa \Z kraj stringa
Važan detalj

Poklapanje nulte dužine

29 / 50
Primer
^\d*$
Problem

Ovaj regex prihvata i prazan string, jer * dozvoljava nula ponavljanja.

Word boundary

Granica reči

30 / 50
Metakarakter
\b
Primer
\bword\b \b4\b
Negacija

Invertovana granica reči

31 / 50
Metakarakter
\B
Značenje

Poklapa pozicije koje nisu granice reči.

Analiza

Kako radi granica reči?

32 / 50
Primer
Regex: \bis\b String: This island is beautiful
Zaključak

Regex poklapa samo samostalnu reč is, a ne deo reči This.

Alternacija

Korišćenje vertikalne crte za alternativni izbor

33 / 50
Primeri
cat|dog cat|dog|mouse|fish
Cele reči
\b(cat|dog)\b
Oprez

Redosled alternativnih izbora je važan

34 / 50
Problematičan regex
Get|GetValue|Set|SetValue
Bolje opcije
GetValue|Get|SetValue|Set Get(Value)?|Set(Value)? \b(Get|Set)(Value)?\b
Operator ?

Opciona polja

35 / 50
Primeri
colou?r Nov(ember)? Feb(ruary)? 23(rd)?
Greediness

Važan koncept: pohlepnost

36 / 50
Primer
Feb 23(rd)?
Efekat

Regex će pokušati da poklopi i opcionu grupu ako je to moguće.

Analiza

Kako radi regex colou?r?

37 / 50
String
The colonel likes the color green
Objašnjenje

Regex će preskočiti slovo u kada ono ne postoji, i uspešno poklopiti color.

Kvantifikatori

Ponavljanje sa znakovima * i +

38 / 50
Značenje
* nijednom ili više puta + jednom ili više puta
Primer
<[A-Za-z][A-Za-z0-9]*> Poklapa HTML tag bez atributa <B> ili <HTML>
Granice

Ograničavajuće ponavljanje

39 / 50
Sintaksa
{min,max}
Primer
\b[1-9][0-9]{3}\b poklapa brojeve od 1000 do 9999
Greedy primer

Oprez na pohlepnost!

40 / 50
Regex
<.+>
Problem
This is a <EM>first</EM> test

Poklapanje će biti <EM>first</EM>, što je pogrešno.

Lazy quantifier

Lenjost umesto pohlepnosti

41 / 50
Lenji regex
<.+?>
Rezultat

Poklapa minimalan broj karaktera (npr. samo <EM>).

Efikasnije rešenje

Alternativa za nevoljnost

42 / 50
Bolji regex
<[^>]+>
Prednost

Efikasnije, bez nepotrebnog backtracking-a.

Zagrade

() za grupisanje

43 / 50
Primer
(Get|Set)(Value)?
Napomena

Obične zagrade grupišu delove regex-a za primenu operatora.

Capturing groups

Obične zagrade kreiraju reference

44 / 50
Primer
Set(Value)?
Optimizacija
Set(?:Value)?
Backreference

Reference u praksi

45 / 50
HTML tagovi
<([A-Z][A-Z0-9]*)>.*?</\1> Šta radi? hvata ime otvarajućeg HTML taga koristi isto ime u zatvarajućem tagu Primer poklapanja: <B><I> bolditalic </I></B>
Primer sekvence
([a-c])x\1x\1
Backreference

Reference i ponavljanje

46 / 50
Pitanje
Koja je razlika između: ([abc]+) i ([abc])+
Odgovor
Na stringu cab: prvi čuva cab drugi čuva samo poslednje poklapanje: b Ovo je veoma važno kod backreference logike.
Backreference

Primer

47 / 50
Uklanjanje duplih reči
Regex: \b(\w+)\s+\1\b Poklapa: master master prosek prosek U tekstu: Student sam master master studija, imam odlican prosek prosek
Java primer

Zamena duplih reči u Javi

48 / 50
Kod
public class JavaRegexExamples { public static final String DOUBLE_WORD_TEST = "Student sam master master studija, imam odlican prosek prosek."; public static void replaceExample() { String pattern = "\\b(\\w+)\\s+\\1\\b"; System.out.println("Izbacivanje dvostrukih reci iz teksta:"); String doubleWordsCorrected = DOUBLE_WORD_TEST.replaceAll(pattern, "$1"); System.out.println(DOUBLE_WORD_TEST + " --> " + doubleWordsCorrected); } public static void main(String[] args) { replaceExample(); } }
Izlaz programa
Izbacivanje dvostrukih reci iz teksta: Student sam master master studija, imam odlican prosek prosek. --> Student sam master studija, imam odlican prosek.
Backreference

Dodatni praktični primeri

49 / 50
Promenljiva u programskom jeziku
[A-Za-z_][A-Za-z_0-9]*
Heksadecimalni broj u C stilu
0[xX][A-Fa-f0-9]+
Reči sa različitim pisanjem
sep[ae]r[ae]te li[cs]en[cs]e
Najčešće greške pri radu sa regex-om
preterano korišćenje tačke . zaboravljeno escape-ovanje metakaraktera ignorisanje pohlepnosti nepostavljanje granica reči \b pogrešna upotreba referenci nerealan pokušaj da regex reši „sve”
Preporuke za praksu
početi od jednostavnih primera testirati regex na više ulaza koristiti granice reči i markere kad god su potrebni koristiti klase karaktera umesto tačke kada je moguće voditi računa o efikasnosti i backtracking-u
Završnica

Zaključak

50 / 50

Regex je nezaobilazan alat za svakog softverskog inženjera.

  • Tačan, čitljiv i efikasan regex je cilj.
  • Vežba je najbolji način za savladavanje.
  • Pitanja?
Savet

Uvek testirajte svoje izraze na realnim podacima.