nav_dugme codeBlog codeBlog
  • početna Početna stranica
  • Sačuvani članci Sačuvani članci
  • Članci
     (spisak)
  • Kontakt
Povratak na vrh stranice

Info & povezani članci Info o članku - dugme

Info

trejler_sat Datum objave: 07.12.2020.

trejler_olovka Poslednja izmena: 12.01.2023.

trejler_dokument Jezici: JavaScript

trejler_teg_narandzasti Težina: 6/10

JavaScript
regularni izrazi
regex
pretraga
optimizacija
niske
tutorijali
saveti
zanimljivosti

Povezani članci

Uvod u JavaScript i DOM (Document Object Model)Regularni izrazi - napredna pretraga tekstaOperacije sa nizovima u programskom jeziku JavaScriptTutorijal - Implementacija struktura podataka u programskom jeziku JavaScriptŠablonske niske u programskim jezicimaJSON - tekstualni format za razmenu podatakaUvod u dinamičko programiranjeUvod u PythonKako napraviti syntax highlighterIzbor prvog programskog jezika
Svi članci
First, solve the problem. Then, write the code.
John Johnson

Tutorijal - Regex i JavaScript - Korišćenje regularnih izraza u programskim jezicima

Facebook LinkedIn Twitter Viber WhatsApp E-mail
zoom_plus zoom_minus bookmark
početna > Članci > Saveti

Uvod

U prethodnom tutorijalu o regularnim izrazima najavili 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), i stoga ćemo se u članku koji je pred nama baviti (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)
Tabela sa opisima/komentarima
Slika 1. - Primer tabele u koju se mogu zapisati komentari koje je potom potrebno integrisati u HTML datoteku.

Zadatak nije nimalo komplikovan (niti težak), pa preostaje da 'natenane' razmotrimo 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")
		
<html>
	<head>
		<meta charset='utf-8'/>
		<script src='obrada.js'></script>
		<link href='stil.css' rel='stylesheet'>
	</head>
	<body>
		<label for='polje_ulaz'>Ulaz:</label>
		<textarea id='polje_ulaz'>
		</textarea>

		<label for='polje_izlaz'>Izlaz:</label>
		<textarea id='polje_izlaz'></textarea>
		
		<button onclick='obrada(KOMENTARI)'>Obrada</button>
	<body>
</html>
		
	
Slika 2. - Sadržaj improvizovane HTML datoteke, sa formularima preko kojih se mogu modifikovati elementi drugih HTML datoteka.

Dodaćemo i (najosnovniji) CSS ....

		
#polje_ulaz {
	display: flex;
	width:   450px;
	height:  150px;
}

#polje_izlaz {
	display: flex;
	width:   450px;
	height:  300px;
}

#polje_ulaz, #polje_izlaz {
	margin-bottom: 1em;
}
		
	
Slika 3. - CSS kod za stilizaciju HTML datoteke sa prethodne slike.

.... 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) ....

		
let KOMENTARI = [
	"" ,
	"Mona Liza (Leonardo da Vinči, 1503)" ,
	"Lovci u snegu (Piter Brojgel Stariji, 1565)" ,
	"" ,
	"Zvezdana noć (Vinsent van Gog, 1889)" ,
	"Gernika (Pablo Pikaso, 1937)" ,
	"" ,
	""
];
		
	
Slika 4. - Komentari sa slike #1, preuzeti iz tabele i uobličeni u vidu JS liste.

.... posle čega možemo početi da se upoznajemo i sa 'tehnikalijama' koje će omogućiti da se različite ideje sprovedu u delo.

Napomena: Veoma je bitno da lista bude formatirana na prikazani način (potrebno je da ručno dodamo prazan element liste - element KOMENTARI[0], koji prethodi elementima koje smo kopirali iz pomoćne tabele).

Bitno je i to da posle kopiranja (to jest, pre nego što formatiramo listu) - ne uklanjamo prazne redove!

Uz uvažavanje navedenih uputstava, postižemo da se indeksi u listi poklope sa indeksima redova iz tabele (čime olakšavamo snalaženje saradniku koji je zadužen za unos opisa u tabelu).

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:

		
Slika 4. - .
		
	
Slika 5. - Primer (praznog) opisa/komentara za img element na HTML stranici.

Izdvajaćemo samo "prazne" komentare - one koje treba prepraviti, tj. dopuniti (u tom smislu, komentar ispod slike #4 na kraju treba da bude: Slika 4. - Zvezdana noć (Vinsent van Gog, 1889)..

Komentar ispod slike potrebno je izdvojiti u celosti, za šta se može koristiti sledeći regularni izraz ....

		
Slika 4\. - \.
		
	
Slika 6. - Regularni izraz koji prepoznaje tekst sa prethodne slike.

.... 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:

		
let regex = new RegExp("Slika 4\. - \.", "g");
		
	
Slika 7. - "Zvanični" način za definisanje regularnog izraza koji prepoznaje tekst sa slike #5.

Regularni izraz koji smo definisali odnosi se (samo) na sliku #4, međutim, moguće je uopštiti sintaksu tako da se regularni izraz (ubuduće) odnosi na bilo koju sliku:

		
let regex = new RegExp("Slika [0-9]+\. - \.", "g");
		
	
Slika 8. - Opšti oblik regularnog izraza koji prepoznaje opis slike.

U novom obliku, regularni izraz se može koristiti za sledeće operacije:

  • pronalaženje poklapanja (preko funkcije match)
  • podelu niski (preko funkcije split)

Prvo ćemo - preko opštih primera - prikazati kako se koriste funkcije match i split, a potom ćemo se vratiti na glavni zadatak.

match - pronalaženje poklapanja

U sledećoj naredbi (koju navodimo u svojstvu opšteg obrasca) ....

		
let poklapanje = s1.match(s2);
		
	
Slika 9. - Opšta šema poziva funkcije match.

.... 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 ....

		
let s1 = "Nemačka"; 
let s2 = "mačka";

let p  = s1.match(s2);
console.log(p);
		
	
Slika 10. - Primer korišćenja funkcije match.

.... 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) ....

		
let lista = s1.split(s2); 
		
	
Slika 11. - Opšta šema poziva funkcije split.

.... funkcija split pronalazi pojave niske s2 unutar niske s1 i pravi 'rezove' na mestima na kojima se (do tada) pojavljivala niska s2, posle čega se od delova ulazne niske (koji su nastali podelom) - formira lista.

Da pojasnimo preko primera: upotrebom funkcije split (u sledećem bloku) ....

		
let s1    = "123-#-231-#-321";
let lista = s1.split("-#-"); 
		
	
Slika 12. - Primer korišćenja funkcije split.

.... nastaje lista sledeće sadržine:

		
[ "123" , "231" , "321" ]
		
	
Slika 13. - Lista koja nastaje izvršavanjem naredbi sa prethodne slike.

Prema podrazumevanim podešavanjima, niska koja je korišćena kao kriterijum za razdvajanje (s2) - ne kopira se u izlaznu listu.

.... naravno, u situacijama kada uopšte dolazi do poklapanja (a napomenimo usput i to da se sadržaj niske s1 ne menja).

Prikazani 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" i sl), međutim (da se vratimo na temu članka), ako bi se ulazni tekst koji je preuzet iz HTML datoteke "provukao" kroz funkciju split, pri čemu bi kriterijum za podelu bio regex za pronalaženje komentara za slike (koji smo ranije videli) - bili bi uklonjeni svi komentari ispod slika!

Doslovno bismo ostali bez onih delova ulaznog teksta - zbog kojih pravimo skriptu. :)

Međutim, podešavanja se mogu izmeniti, što praktično znači da se problem može rešiti prigodnim formatiranjem niske koja se koristi kao kriterijum za razdvajanje (uzećemo ponešto izmenjen primer sa slike #12):

		
let s1    = "Ivan;Marković;381060222555;"
let regex = new RegExp("((?<=;)[0-9]+(?=;))", "gm"); 
let lista = s1.split(regex); 
		
	
Slika 14. - Primer korišćenja funkcije split, koji prikazuje podelu pri kojoj se ne uklanjaju delimiteri.

Dakle: ako je potrebno da se u izlaznu listu kopiraju i delimiteri (tj. niske koje se uklapaju u obrazac za pretragu) - regularni izraz se uokviruje zagradama.

Pokretanjem instrukcija sa gornje slike, dobija se sledeća lista:

		
[ "Ivan;Marković;" , "381060222555" , ";" ]
		
	
Slika 15. - Rezultat izvršavanja skripte sa prethodne slike.

Podaci koje smo dobili kao rezultat (u gornjem primeru), omogućavaju npr. da u daljoj obradi formatiramo broj telefona na pregledniji način: +381 060/222-555 i sl.

Osvrnimo se i na jednostavan primer podele HTML koda (recimo da je potrebno ukloniti 'underline' tagove, ali - ne i unutrašnji sadržaj tagova):

		
let s1    = "<p>Triput <u>meri</u> - jednom seci</p>"
let regex = new RegExp("(<u>|</u>)", "gm"); 
let lista = s1.split(regex);
		
	
Slika 16. - Jednostavan primer podele HTML koda (bez uklanjanja delimitera).

Unutar liste (koju smo dobili preko funkcije split) ....

		
[
	"<p>Triput " ,
	"<u>" ,
	"meri" ,
	"</u>" ,
	" - jednom seci</p>"
]
		
	
Slika 17. - Rezultat izvršavanja naredbi sa prethodne slike.

.... sada lako možemo pronaći <u> tagove i ukloniti ih.

Pomoćne funkcije

.... "iz domaće radinosti"

Smatramo da će naredno poglavlje (u kome ćemo prikazati implementaciju skripte za "utiskivanje komentara"), biti preglednije ukoliko se prethodno osvrnemo na nekoliko pomoćnih funkcija.

Posle podele preko funkcije split (sa kojom smo se upoznali u prethodnom poglavlju), 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):

		
function citanjeIndeksaSlike(s, ind) {
	let s2    = "";
	let uslov = daLiJeCifra(s[ind]);

	while (ind < s.length && uslov) {
		s2 += s[ind];
		++ind;
		uslov = daLiJeCifra(s[ind]);
	}

	return parseInt(s2);
}
		
	
Slika 18. - Implementacija funkcije citanjeIndeksaSlike.

Jednostavnu funkciju daLiJeCifra takođe ćemo implementirati sami (cifra je svaki znak čija je ASCII vrednost između 48 i 57, odnosno, između '0' i '9'):

		
function daLiJeCifra(c) {
	return c >= '0' && c <= '9';
}
		
	
Slika 19. - Implementacija funkcije daLiJeCifra.

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:

		
function formatiranjeNovogKomentara(i, k) {
	return `Slika ${i}. - ${k}.`; 
}

// i - indeks
// k - komentar
		
	
Slika 20. - Implementacija funkcije formatiranjeNovogKomentara.

Funkciju formatiranjeNovogKomentara, iskoristićemo unutar funkcije koja prepravlja element liste za koji je (unutar liste KOMENTARI), pronađen novi komentar:

		
function utiskivanjeKomentara(lista, indeks, komentari) {
	let i = citanjeIndeksaSlike(lista[indeks], 6);
	let k = komentari[i];

	// Ukoliko u nekom trenutku prepravite skriptu
	// tako da se u obzir uzimaju i komentari koji
	// već imaju određeni sadržaj, aktivirajte
	// donji uslov:

	// if (k[i] == "") return;

	lista[indeks] = formatiranjeNovogKomentara(k, i);
}
		
	
Slika 21. - Implementacija funkcije utiskivanjeKomentara.

Da pojasnimo kod koji smo videli:

  • lista - lista koja je dobijena podelom ulaznog teksta
  • indeks - indeks u listi (koja je dobijena podelom ulaznog teksta), na kome je pronađen komentar za sliku koji treba dopuniti
  • komentari - lista komentara (koja je uvezena iz spoljne tabele) *
  • i - indeks slike koji je pročitan iz elementa liste lista koji sadrži komentar koji treba dopuniti
  • k - komentar (niska iz liste komentari * koja odgovara indeksu i)

Preko poslednje naredbe: lista[indeks] = formatiranjeNovogKomentara(k, i), 'utiskuje' se novi komentar.

* Praktično: parametar komentari se povezuje sa listom KOMENTARI, koju smo napravili na početku.

Na kraju, pripremićemo i pomoćnu funkciju koja spaja elemente liste u nisku:

		
function spajanjeListe(lista) {
	return lista.join("");
}
		
	
Slika 22. - Implementacija funkcije spajanjeListe.

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 se upoznali 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"

Funkcija obrada (preko koje se neposredno pokreće obrada teksta), može se implementirati na sledeći način:

		
function obrada(komentari) {
	let poljeUlaz  = document.getElementById("polje_ulaz");
	let poljeIzlaz = document.getElementById("polje_izlaz");

	let regex = new RegExp("(Slika [0-9]+\\. - \\.)", "gm")
	let s     = poljeUlaz.innerHTML;
	let lista = s.split(regex);

	for (let i = 0; i < lista.length; ++i) {
		if (lista[i].match(regex)) {
			utiskivanjeKomentara(lista, i, komentari);
		}
	}

	poljeIzlaz.innerHTML = spajanjeListe(lista);
}
		
	
Slika 23. - Implementacija glavne funkcije (preko koje se neposredno pokreće obrada podataka).

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 pišemo o regularnim izrazima i u budućnosti).

Za kraj (za vežbu), probajte da samostalno napišete JS skriptu koja će npr. svim <h2> elementima automatski dodeljivati id-ove u skladu sa pozicijom <h2> elementa u strukturi HTML dokumenta (tako da prvi <h2> element dobije id "podnaslov_h2_01", drugi <h2> dobije id "podnaslov_h2_02" i sl).

Autor članka Nikola Vukićević Za web portal codeblog.rs
Napomena: Tekstovi, slike, web aplikacije i svi ostali sadržaji na sajtu codeblog.rs (osim u slučajevima gde je drugačije navedeno) predstavljaju intelektualnu svojinu autora sajta codeblog.rs i zabranjeno je njihovo korišćenje na drugim sajtovima i štampanim medijima, kao i bilo kakvo drugo korišćenje u komercijalne svrhe, bez eksplicitnog pismenog odobrenja autora.
© 2020-2026. Sva prava zadržana.
Facebook LinkedIn Twitter Viber WhatsApp E-mail
početna > Članci > Tutorijal - Regex i JavaScript - Korišćenje regularnih izraza u programskim jezicima
codeBlog codeBlog
Sajt posvećen popularizaciji kulture i veštine programiranja.
Napomena: Tekstovi i slike na sajtu codeblog.rs (osim u slučajevima, gde je drugačije navedeno) predstavljaju intelektualnu svojinu autora sajta codeblog.rs i zabranjeno je njihovo korišćenje na drugim sajtovima i štampanim medijima, kao i bilo kakvo drugo korišćenje u komercijalne svrhe, bez eksplicitnog odobrenja autora.
© 2020-2026. Sva prava zadržana.
Facebook - logo
Instagram - logo
LinkedIn - logo
Twitter - logo
E-mail
Naslovna
   •
Uslovi korišćenja
   •
Obaveštenja
   •
FAQ
   •
Kontakt