Uvod
Obećali smo u prethodnom tutorijalu o regularnim izrazima, da ćemo se u nekom trenutku pozabaviti povezivanjem regularnih izraza sa programskim jezicima (i ovoga puta, bavićemo se upravo time).
Da bismo se na pravi način posvetili temi, postavićemo početni problem:
- Potrebno je kreirati HTML dokument koji sadrži slike sa komentarima/opisima
- U izradi dokumenta učestvuju dve osobe: web dizajner, zadužen za "tehnikalije" (kreiranje HTML-a, raspored tagova i sl.) i druga osoba, čiji je posao da napiše komentare/opise slika koje se pojavljuju na sajtu
- Osoba zadužena za komentare neće unositi komentare direktno u HTML (to je posao web dizajnera), već će web dizajneru predati Excel tabelu (iz koje lako možemo kopirati tekst koji nem je potreban), ili jednostavno - običan tekstualni dokument sa gotovim opisima
- Web dizajner na kraju ima na raspolaganju: HTML (koji je kreirao sam) i tekstualnu datoteku sa opisima, koju je dobio od svog saradnika (pri čemu se indeksi slika u HTML dokumentu i tekstualnoj datoteci sa opisima poklapaju)
Dakle, potrebno je komentare/opise integrisati u HTML dokument (i pitamo se kako da to izvedemo) ....
Detaljan opis problema
Pre nego što se zapitate zašto uopšte za ovako nešto moramo koristiti regularne izraze, malo ćemo zakomplikovati "propozicije" dodatnim zahtevima:
- Osoba zadužena za komentare, neće uneti sve komentare/opise, već samo one najvažnije (dok će ostale komentare uneti web dizajner
- Neki od kometara koje je web dizajner uneo će po potrebi biti zamenjeni (opširnijim/boljim komentarima)
Ovim smo onemogućeni da komentare tražimo po jednostavnom obrascu pretrage, jer bi to dovelo do toga da se postojeći komentari koje je web dizajner uneo u dokument, doslovno spoje sa komentarima koji se naknadno unose, pa se stoga (ipak) moramo osloniti na regularne izraze.
U bilo kom ozbiljnijem editoru (kao što već znate), postoji podrška za regularne izraze. U svakom trenutku možemo napisati regularni izraz sledećeg oblika ....
Slika 15. - .*
.... i program će pronaći ceo red sa komentarom za sliku 15 (posle čega pronađeni tekst možemo zameniti drugim proizvoljnim tekstom).
Naravno, za ostale slike morali bismo da ponovimo postupak, tako što bismo svaki put "ručno" menjali broj u regularnom izrazu (i naravno tekst kojim želimo da zamenimo pronađeni obrazac).
Ukoliko je broj komentara mali (recimo, manji od deset), ceo posao možemo završiti brzo i bez mnogo muke. Ali, ako je broj komentara veliki (više desetina, ili preko 100), ovakav posao nije ni malo "zabavan".
Editori nemaju kontrolne strukture kao što su petlje, niti druge načine za umetanje vrednosti promenljivih u regularne izraze, ali, programski jezici imaju ove mogućnosti i naravno - podršku za regularne izraze (svi iole relevantni/popularni jezici).
U našem primeru, koristićemo programski jezik JavaScript, kao najpogodniji za "brzinsko" isprobavanje primera koje ćemo izneti (ali, naravno da vas ohrabrujemo da samostalno istražujete upotrebu regularnih izraza u drugim programskim jezicima, a takođe, na našim stranicama ćete u budućnosti moći da čitate i članke o korišćenju regularnih izraza u programskim jezicima Java, Python i C#) i takođe, koristićemo samo jednostavne regularne izraze primerene problemu kojim se bavimo.
Implementacija rešenja u programskom jeziku JavaScript
Ostavićemo našim čitaocima da sami pripreme HTML dokument preko koga ćemo pokretati JavaScript kod. Potrebno je da dati dokument sadrži:
- textarea element sa id-om "input_regex_html" (u koji ćemo kopirati HTML dokument u koji je potrebno integrisati komentare/opise slika)
- textarea element sa id-om "input_regex_komentari" (u ovaj odeljak kopiraćemo spisak komentara)
- button za pokretanje JS-a
Prvo iskoristite button koji ste ubacili da pokrenete sledeći kod koji prikazuje osnovnu funkcionalnost regularnih izraza u JavaScript-u:
function regexProba {
let s = "Proba regex-a u jeziku JavaScript i ostakak stringa ....";
let regex = new RegExp("JavaScript.*", "g");
let p = s.match(regex);
console.log(p);
alert(p);
}
Regularni izraz koji koristimo je:
JavaScript.*
.... što znači da tražimo deo stringa koji počinje podstringom "JavaScript" i (podrazumevano) se završava prelaskom u novi red (možemo i to da zaobiđemo, odnosno, da tražimo obrasce koji se "protežu" preko više redova - više o tome u nastavku).
Funkcija match() ....
let p = s.match(regex);
.... vraća string koji odgovara poklapanju koje tražimo unutar stringa s.
Primetili ste i direktivu "g", u inicijalizaciji RegExp objekta ....
let regex = new RegExp("JavaScript", "g");
U pitanju je direktiva koja nalaže programu da nastavi sa traženjem poklapanja i nakon što se pronađe prvo odgovarajuće poklapanje (u suprotnom, program se zaustavlja čim pronađe prvo poklapanje).
Ukoliko datu direktivu dopunimo direktivom "m", odnosno, napišemo direktivu "gm", program će tražiti sva poklapanja ("g") i sprovoditi pretragu se ne zaustavlja pri prelasku u novi red (što je, kao što smo maločas naveli, podrazumevana situacija).
Sada možemo napisati i punu implementaciju za naš primer. Kao prvo, pomoćna funkcija koja učitava komentare iz odgovarajućeg textarea elementa:
var KOMENTARI = [""];
function ucitavanjeKomentara() {
let s = document.getElementById("input_regex_komentari").value;
KOMENTARI = KOMENTARI.concat(s.split('\n'));
// s.split('\n'); - Tekst se deli na niz stringova, a kriterijum za
// podelu je pojava znaka za prelazak u novi red
// KOMENTARI.concat() - Globalnoj promenljivoj KOMENTARI, koja je
// inicijalizovana kao niz sa jednim praznim
// stringom, dodaje se niz stringova
//console.log(KOMENTARI);
}
Osnovna ideja ovakve funkcije je da se indeksi slika poklope sa redovima u tekstualnom dokumentu (komentar za sliku 1. zapisan je u prvom redu, za sliku 2. u drugom i tako redom). Ukoliko smo pravilno zapisali komentare, funkcija split() će uredno od unetog teksta kreirati niz stringova u kome će indeksi niza odgovarati redovima (upravo se iz ovog razloga, niz KOMENTARI inicijalizuje jednim praznim stringom, čiji je indeks 0).
.... a zatim i funkciju koja obavlja zamenu:
function azuriranjeKomentara() {
ucitavanjeKomentara();
let regex;
let s = document.getElementById("input_regex_html").value;
let i, d = KOMENTARI.length;
for(i = 0; i < d; i++) {
// Ukoliko osoba zadužena za komentare nije napisala komentar za
// određenu sliku, ostaće komentar koji je uneo web dizajner:
if(KOMENTARI[i] == null) continue;
regex = new RegExp("Slika " + i + ". - .*", "gm");
s = s.replace(regex, KOMENTARI[i]);
}
document.getElementById("input_regex_html").value = s;
}
Vidimo da je glavni deo ove funkcije naredba:
s = s.replace(regex, KOMENTARI[i]);
Funkcija replace prvo pronalazi poklapanje preko regex-a (isto kao i funkcija match), a potom pronađeni obrazac menja tekstom koji je naveden (u našem slučaju, to je jedan od elemenata niza KOMENTARI, odnosno, upravo komentar koji odgovara traženoj slici, pri čemu smo poklapanje obavili preko indexa i).
U smislu uparivanja indeksa slika sa odgovarajućim komentarima, najbitniji (i za proučavanje najzanimljiviji) deo je sledeća for petlja:
for(i = 0; i < d; i++) {
regex = new RegExp("Slika " + i + ". - .*", "gm");
....
}
Jednostavno, za svaku vrednost promenljive i, obavljamo inicijalizaciju objekta regex i dodeljujemo mu obrazac za pretragu koji navodi indeks slike koji se poklapa sa promenljivom i (pri čemu kreiramo pretrage: "Slika 1. - .*", "Slika 2. - .*" .... i tako redom, do poslednjeg indeksa).
Upravo je ovo (kreiranje jednostavnog programa), ono što nismo mogli da obavimo u običnom editoru teksta (koji nema podršku za promenljive, niti ima kontrolne strukture kao što su petlje) i na ovakvom jednostavnom primeru možemo sagledati pravu lepotu programiranja - sposobnost čoveka da pomogne sebi tako što će za obavljanje "dosadnih", pomoćnih zadataka - "uposliti" računar.
Zaključak
Nadamo se da smo vas ovim člankom zainteresovali da dalje istražujete ovu tematiku (a mi ćemo svakako, kao što smo već rekli, nastaviti da o regularnim izrazima pišemo i u budućnosti).
Za kraj (za vežbu), probajte samostalno da napišete JavaScript koji će svim h2 elementima automatski dodeljivati id-ove u skladu sa pozicijom h2 elementa u strukturi dokumenta (prvi h2 element dobija id "podnaslov_h2_01", drugi, "podnaslov_h2_02" i tako redom).