Tutorijal - Regex i JavaScript - Korišćenje regularnih izraza u programskim jezicima
Uvod
U prethodnom tutorijalu o regularnim izrazima naveli smo da ćemo u bliskoj budućnosti prikazati kako se regularni izrazi mogu koristiti u programskim jezicima (što sasvim verovatno predstavlja najzanimljiviji vid upotrebe regex obrazaca).
U članku koji je pred nama, bavićemo se (upravo), rešavanjem problema uz korišćenje regularnih izraza u JavaScript-u, pri čemu ćemo razmotriti (kako i dolikuje za početak), veoma jednostavan primer:
- HTML stranica sadrži veći broj slika
- potrebno je da se ispod svake slike nađe opis (tj. komentar)
- postoji mogućnost da ćemo pisanje komentara za slike poveriti drugom saradniku, koji će komentare zapisati u tabelu (u formatu koji je prikazan na slici #1)
- komentare iz tabele potrebno je ubaciti u HTML dokument (pri čemu se redni broj slike na HTML stranici, poklapa sa oznakom reda u tabeli)
Zadatak nije nimalo komplikovan (niti težak), i stoga ćemo 'natenane' razmotriti ideje koje stoje iza skripte koju treba napraviti, a upoznaćemo se usput i sa nekoliko osnovnih funkcija iz JavaScript-a, sa kojima se do sada nismo sretali ....
Razrada ideja ....
Za početak, potrebno je spremiti jednostavnu improvizovanu HTML stranicu koja omogućava:
- unos HTML kodova sa nepotpunim opisima slika (preko polja sa id-om "polje_ulaz")
- prikaz izmenjenih (tj. dopunjenih) HTML kodova (preko polja sa id-om "polje_izlaz")
Dodaćemo i (najosnovniji) CSS ....
.... da bi elementi stranice bili raspoređeni na vizuelno dopadljiviji način.
Sadržaj komentara najpraktičnije je uneti direktno u JS skriptu obrada.js
(koja je povezana sa prethodno definisanom HTML stranicom) ....
.... posle čega možemo početi da se upoznajemo i sa 'tehnikalijama' koje će omogućiti da se različite ideje sprovedu u delo.
Pre nego što pređemo na konkretne funkcije preko kojih se rešava glavni zadatak, ukratko ćemo prodiskutovati o tome kako se (uopšte), u JavaScriptu - preko regularnih izraza - mogu pronalaziti elementi i kako se preko regularnih izraza od niski mogu kreirati liste.
Osnovne JS funkcije za rad sa regularnim izrazima (match, split i replace)
U svojstvu primera, uzmimo da je potrebno pronaći sadržaj komentara za sliku #4, ispod koje stoji sledeći opis:
Komentar ispod slike, potrebno je izdvojiti u celosti, za šta se može koristiti sledeći regularni izraz:
.... s tim da ćemo regularne izraze u JavaScript-u, u ovom članku (a najčešće i inače), definisati na 'zvaničan' način:
Regularni izraz koji smo definisali, odnosi se (samo) na sliku #4, međutim, lako je moguće uopštiti sintaksu tako da se regularni izraz (ubuduće) odnosi na bilo koju sliku:
U novom obliku, regularni izraz se može koristiti za sledeće operacije:
- pronalaženje poklapanja (preko funkcije
match
) - podelu niski (preko funkcije
split
)
match - pronalaženje poklapanja
U sledećoj naredbi (koju navodimo u svojstvu opšteg obrasca):
.... funkcija match
traži prvi indeks, unutar niske s1
, na kome počinje poklapanje niske s2
sa delom niske s1
.
Na primer, sledeći kod ....
.... ispisaće u konzoli vrednost 2 (poklapanje počinje na 3. poziciji u niski s1
, to jest, u pitanju je indeks 2).
Ukoliko poklapanje ne postoji, funkcija match
vraća vrednost null
.
split - podela niske
U sledećoj naredbi (pri čemu je i ovoga puta u pitanju opšta šema) ....
.... funkcija split
pronalazi pojave niske s2
unutar niske s1
i pravi 'rezove' na mestima na kojima se (do tada) pojavljivala niska s1
, posle čega se od delova ulazne niske (koji su nastali podelom) - formira lista.
Da pojasnimo preko primera: upotrebom funkcije split
(u sledećem bloku) ....
.... nastaje lista sledeće sadržine:
Prema podrazumevanim podešavanjima, niska koja je korišćena kao kriterijum za razdvajanje (s2) - ne kopira se u izlaznu listu.
Navedeni pristup dobro dođe u situacijama kada su niske (tipično - tekstualne datoteke), formatirane na način koji korisnicima omogućava da (praktično) naznače polja tabele u okviru jednog reda (na primer: "Ivan ; Marković ; markovic_i@domen.rs"
), međutim (da se vratimo na temu članka), ako se ulazni tekst koji je preuzet iz HTML datoteke "provuče" kroz funkciju split
(pri čemu bi kriterijum za podelu bio regex za pronalaženje komentara za slike, koji smo ranije videli) - biće uklonjeni svi komentari ispod slika!
Međutim, podešavanja se mogu izmeniti, i problem se rešava prigodnim formatiranjem niske koja se koristi kao kriterijum za razdvajanje (uzećemo ponešto izmenjen primer sa slike #12):
Dakle: ako je potrebno da se u izlaznu listu kopiraju i delimiteri (niske koje se koriste kao obrazac za pretragu) - regularni izraz se uokviruje zagradama.
Pokretanjem instrukcija sa gornje slike, dobija se sledeća lista:
Osvrnimo se i na jednostavan primer podele HTML koda (recimo da je potrebno ukloniti 'underline' tagove, ali - ne i unutrašnji sadržaj tagova):
Unutar liste (koju smo dobili preko funkcije split
) ....
.... sada lako možemo pronaći <u>
tagove i ukloniti ih.
Pomoćne funkcije "iz domaće radinosti"
Smatramo da će naredni odeljak (u kome ćemo prikazati implementaciju skripte za "utiskivanje komentara"), biti pregledniji ukoliko se prethodno osvrnemo na nekoliko pomoćnih funkcija.
Posle podele preko funkcije split
(sa kojom smo se upoznali u prethodnom odeljku), određeni elementi liste imaće sadržaj po obrascu Slika #. - .
(gde znak #
zapravo označava redni broj slike), a kada element liste koji se poklapa sa navedenim obrascem dospe na obradu, biće potrebno da skripta pročita redni broj slike (koji je deo niske).
Ideja je sledeća: počevši od sedmog znaka (indeks 6; prva cifra u izdvojenoj niski), čitaju se redom sve cifre i smeštaju se u pomoćnu nisku - koja se na kraju pretvara u celobrojnu promenljivu (preko funkcije parseInt
):
Funkcija daLiJeCifra
takođe će biti implementirana u 'domaćoj radinosti' (cifra je svaki znak čija je ASCII vrednost između 48 i 57, odnosno, između '0' i '9'):
Kada skripta pročita (novi) komentar iz liste KOMENTARI
(i pošto je prethodno ustanovljen indeks slike za koju se traži opis), najelegantnije je da se opis slike formatira preko zasebne funkcije:
Funkciju formatiranjeNovogKomentara
, iskoristićemo unutar funkcije koja prepravlja element liste za koji je (unutar liste KOMENTARI
), pronađen novi komentar:
Da pojasnimo kod koji smo videli:
lista
- lista koja je dobijena podelom ulaznog tekstaindeks
- indeks u listi (koja je dobijena podelom ulaznog teksta), na kome je pronađen komentar za sliku koji treba dopunitikomentari
- lista komentara (koja je uvezena iz spoljne tabele) *i
- indeks slike koji je pročitan iz elementa listelista
koji sadrži komentar koji treba dopunitik
- komentar (niska iz listekomentari
* koja odgovara indeksui
)
Preko poslednje naredbe: lista[indeks] = formatiranjeNovogKomentara(k, i)
- 'utiskuje' se novi komentar.
Na kraju, pripremićemo i pomoćnu funkciju koja spaja elemente liste u nisku:
U praktičnom smislu, izlaz funkcije spajanjeListe
je konačni rezultat izvršavanja skripte (to jest, novi sadržaj HTML dokumenta).
Implementacija skripte za dodavanje komentara
Pošto smo upoznati sa tehnikalijama, usmerićemo se na kreiranje glavne funkcije, pri čemu se ceo postupak može podeliti na sledeće korake:
- preuzimanje sadržaja iz tekstualnog polja (
"polje_ulaz"
) - podela preuzete niske preko regularnog izraza i (zatim), kreiranje liste
- prolazak (preko petlje), kroz listu koja je kreirana u prethodnom koraku (pri čemu se traže elementi liste koji su formatirani po obrascu:
Slika [0-9]+\. - \.
)
Kada se unutar petlje pronađe element liste koji odgovara prethodno navedenom obrascu, element se prosleđuje funkciji utiskivanjeKomentara
(zarad dalje obrade preko pomoćnih funkcija koje smo ranije definisali):
- preko funkcije
citanjeIndeksaSlike
, čita se indeks slike koji je upisan unutar elementa liste (cifre se pojavljuju neposredno posle niske"Slika "
) - u listi
KOMENTARI
(koja je popunjena još na početku), pronalazi se komentar koji odgovara indeksu koji je očitan u prethodnom koraku - ako komentar (iz liste
KOMENTARI
), koji je pronađen u prethodnom koraku - nije prazna niska - formatira se novi komentar i menja se sadržaj elementa osnovne liste (koji je trenutno u obradi) - na kraju, elementi prepravljene liste (koja je nastala podelom sadržaja ulaznog polja), spajaju se u nisku, koja se usmerava u polje sa id-om
"polje_izlaz"
Funkciju obrada
(preko koje se neposredno pokreće obrada teksta), može se implementirati na sledeći način:
Budući da smo već 'pretresli' sve detalje implementacije, funkcija obrada
deluje (nadamo se), sasvim jednostavno. :)
Sledeći koraci ....
Nadamo se i da smo vas ovakvim člankom zainteresovali da dodatno istražujete mogućnosti upotrebe regularnih izraza u programskim jezicima (a mi ćemo svakako nastaviti da o regularnim izrazima pišemo i u budućnosti).
Za kraj (za vežbu), probajte da samostalno napišete JS skriptu koja će svim <h2>
elementima automatski dodeljivati id-ove u skladu sa pozicijom <h2>
elementa u strukturi HTML dokumenta (tako da prvi <h2>
element dobija id "podnaslov_h2_01", drugi <h2>
dobije id "podnaslov_h2_02" i sl).