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

trejler_dokument Jezici: ----

trejler_teg_narandzasti Težina: 7/10

pretraga
regularni izrazi
regex
obrada teksta
niske
teorija
saveti

Povezani članci

Regularni izrazi - napredna pretraga tekstaTutorijal - Regex i JavaScript - Korišćenje regularnih izraza u programskim jezicimaSyntax highlighter - Regularni izrazi u JavaScript-uShunting Yard - Implementacija - 1. deo - Prevođenje izraza iz infiksnog u postfiksni zapisŠablonske niske u programskim jezicimaOperacije sa nizovima u programskom jeziku JavaScriptOperacije sa bitovima u programskom jeziku CUvod u PythonIzbor prvog programskog jezikaASCII, Unicode i UTF - Predstavljanje znakova na računarimaGNU/Linux - 1. deo - Uvod
Svi članci
There are only two kinds of programming languages: those people always bitch about and those nobody uses.
Bjarne Stroustrup

Tutorijal - Regex - Kako pronaći unutrašnji sadržaj HTML elemenata

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

Uvod

U uvodnom članku o regularnim izrazima pisali smo o osnovnim odlikama regularnih izraza i opštoj upotrebnoj vrednosti regularnih izraza u pronalaženju tekstualnih obrazaca, a ovoga puta pozabavićemo se konkretnim primerom pronalaženja unutrašnjeg sadržaja HTML tagova (tj. sadržaja koji se najpraktičnije može shvatiti kao "innerHTML određenog elementa").

Za sam početak, upoznaćemo se sa operatorima (sa kojima se nismo prethodno upoznali), koji omogućavaju da se navedeni zahvat sprovede u delo ....

Operatori pogleda unapred i pogleda unazad

Operatori pogleda unapred (eng. lookahead) i pogleda unazad (eng. lookbehind), omogućavaju pronalaženje obrazaca koji se nalaze neposredno pre ili neposredno posle pojave drugog obrasca.

Bilo koji od dva 'obrasca' može biti: ili obična niska, ili (praktično), regularni izraz.

Operator pogleda unapred (lookahead) - (?=)

Operator pogleda unapred, pronalazi u tekstu određeni tekstualni obrazac posle koga sledi drugi tekstualni obrazac (koji je neposredno vezan za operator pogleda unapred).

Regularni izraz formira se navođenjem obrasca koji se zapravo pretražuje (obrazac_1), posle čega, unutar zagrada, sledi drugi obrazac (obrazac_2), kome prethodi niska ?=:

		
obrazac_1(?=obrazac_2)
		
	
Slika 1. - Opšta forma operatora pogleda unapred (eng. lookahead).

Rezultat pretrage ulaznog teksta je obrazac_1, ali - samo ako se neposredno iza pojavljuje obrazac_2.

Da bismo bolje razumeli prethodno navedene smernice, razmotrićemo sledeći regularni izraz:

		
meta(?=fizika)
		
	
Slika 2. - Primer upotrebe operatora pogleda unapred.

Pod uslovom da u tekstu postoji podniska koja odgovara obrascu za pretragu:

  • rezultat pretrage je prva niska "meta" posle koje sledi niska "fizika"
  • niska "fizika" nije deo rezultata
  • u pretrazi će biti zanemarena bilo koja pojava niske "meta" posle koje ne sledi niska "fizika"

Najprostije rečeno, operator lookahead pronalazi nisku čiji sam kraj predstavlja početnu poziciju druge niske, koja je (takođe) navedena u obrascu za pretragu.

Operator pogleda unazad (lookbehind) - (?<=)

Operator pogleda unazad (u idejnom smislu, veoma slično kao operator pogleda unapred, ali - 'u obrnutom smeru'), pronalazi obrazac koji se zapravo pretražuje (obrazac_1) - kome prethodi drugi obrazac (obrazac_2).

		
(?<=obrazac_2)obrazac_1
		
	
Slika 3. - Opšta forma operatora pogleda unazad (eng. lookbehind).

Rezultat pretrage ulaznog teksta je (ponovo) obrazac_1, ali, samo ako se neposredno ispred pojavljuje obrazac_2.

I ovoga puta ćemo iskoristiti konkretan primer da otklonimo eventualne nedoumice: kreiraćemo regularni izraz koji praktično pronalazi ceo broj telefona (sa pozivnim brojem), ali - tako da se kao rezultat vraća samo deo posle pozivnog broja.

		
(?<=\d{3}\/)[0-9-]{6,9}
		
	
Slika 4. - Primer upotrebe operatora pogleda unazad.

Da pojasnimo dodatno: sledeći regularni izraz ....

		
\d{3}\/
		
	
Slika 5. - Primer upotrebe operatora pogleda unazad - obrazac unutar operatora.

.... pronalazi nisku od tri cifre posle koje sledi znak '/', ali - budući da je u primeru takav izraz upotrebljen kao obrazac za pretragu unutar operatora lookbehind, praktična svrha obrasca je pronalaženje (tj. označavanje) početka niske koja je definisana na sledeći način ....

		
[0-9-]{6, 9}
		
	
Slika 6. - Primer upotrebe operatora pogleda unazad - niska koju zapravo tražimo.

.... pri čemu je u pitanju niska koja predstavlja broj telefona bez pozivnog broja.

Niska se sastoji od cifara i znakova '-', tako da ukupna dužina niske može biti između: šest znakova (recimo, kratak broj sa pet cifara i jednom crticom, npr. "62-544"), i devet znakova (tipičan broj sa sedam cifara i dve crtice, npr. "21-12-323").

Nažalost, postoji i jedna krajnje bitna razlika između dva operatora o kojima diskutujemo: operator pogleda unazad ne dozvoljava (u većini implementacija) upotrebu obrazaca proizvoljne širine u svojstvu kriterijuma za pretragu, već samo obrazaca fiksne širine.

Pogledajmo sada i (prilično uobičajen u svakodnevnoj praksi), primer koji smo najavili.

Primer - Prepoznavanje unutrašnjeg sadržaja HTML tagova ("innerHTML")

Pretpostavićemo da nam je na raspolaganju HTML lista, čije elemente treba korpirati u određeni dokument tj. 'neki drugi dokument', ali (kao što smo nagovestili) - bez <li> tagova.

Sama niska unutar <li> tagova (smatraćemo tako), može sadržati bilo kakve znakove, a kao što znamo, regularni izraz koji definiše nisku koja može sadržati "bilo koji broj bilo kakvih znakova", zapisuje se na sledeći način: .*.

Tačka označava "bilo koji znak", a znak * označava "bilo koji broj ponavljanja" (a ako želimo da budemo sigurni da nećemo birati prazne <li> tagove, umesto znaka * možemo staviti znak +, koji određuje da se neki od znakova iz navedene klase znakova mora pojaviti bar jednom) ....

Obrazac za pretragu u operatoru lookbehind, biće (doslovno) niska <li>, dok će obrazac u operatoru lookahead, biti niska </li>, i stoga ceo regularni izraz ima sledeći oblik:

		
(?<=<li>).*(?=</li>)
		
	
Slika 7. - Regularni izraz za pronalaženje unutrašnjeg sadržaja <li> tagova.

Pretpostavljamo da je već jasno kako regularni izraz funkcioniše, ali, sledi dodatno objašnjenje.

Prvi deo obrasca ....

		
(?<=<li>).*
		
	
Slika 8. - Regularni izraz za pronalaženje unutrašnjeg sadržaja <li> tagova - prvi deo.

.... traži niske (bilo koje dužine i sadržine, s obzirom na to da smo naveli .*), kojima prethodi niska <li>, dok obrazac ....

		
.*(?=</li>)
		
	
Slika 9. - Regularni izraz za pronalaženje unutrašnjeg sadržaja <li> tagova - drugi deo.

.... traži niske (ponovo: bilo koje dužine i sadržine, s obzirom na to da smo naveli .*), koje se završavaju niskom </li>.

Kada spojimo dva obrasca (onako kako smo već videli), dobija se obrazac za pronalaženje niski koje počinju posle otvarajućeg <li> taga i završavaju se pre početka zatvarajućeg </li> taga.

Šta se ne može izvesti kombinacijom operatora lookahead i lookbehind

Shodno primerima koje smo videli u prethodnom odeljku, pretpostavićemo da bi mnogim čitaocima moglo pasti na pamet da se operator lookbehind takođe može koristiti i za prepoznavanje tagova bilo kog tipa i sadržine, sa navedenim id-ovima, klasama i atributima (recimo, nešto nalik na obrazac koji bi inače prepoznavao otvarajuće <a> tagove - <a.*>) ....

		
(?=<a.*>).*
		
	
Slika 10. - Operator 'lookbehind', koji ne funkcioniše u većini implementacija regex-a (budući da u većini implementacija nije dozvoljeno navoditi proizvoljnu širinu obrasca za pretragu).

.... međutim, kao što smo ranije nagovestili - u navedenoj situaciji postoji problem.

Operator pogleda unapred (da se podsetimo), ne dozvoljava navođenje obrazaca proizvoljne širine (već samo obrazaca fiksne širine).

Navedeno ograničenje je i dalje aktuelno u većini implementacija regex-a, i stoga je u takvim okolnostima potrebno "dovijati" se na druge načine (čime ćemo se takođe uskoro pozabaviti, ali, u nekom od narednih članaka).

Za kraj, pogledajmo i alternativne verzije operatora pogleda unapred i unazad.

Odrednica "!" - negativni pogled unapred i unazad

Pored prethodno navedenih oblika, operatori pogleda unapred i unazad mogu se definisati i na drugi način (naravno, sa sasvim drugačijim (tj. suprotnim) značenjem).

Ukoliko se u operatorima upotrebi znak ! - umesto znaka =, rezultat su isključivi (tj. "negativni") operatori pogleda unapred i unazad.

Recimo, sledeći regex (negativni pogled unapred) ....

		
Petar(?! Jovanović)
		
	
Slika 11. - Negativni pogled unapred - primer.

.... pronalazi pojave imena "Petar" - posle kojih NE sledi prezime "Jovanović".

Za negativni pogled unazad, osvrnućemo se ponovo na primer sa brojevima telefona.

Sledeći izraz ....

		
(?<!\d{3}\/)[0-9-]{6,9}
		
	
Slika 12. - Negativni pogled unazad - primer.

.... ovoga puta traži brojeve telefona kojima nedostaje pozivni broj (to jest, pretražuju se kombinacije cifara i crtica, dužine 6 do 9 znakova - kojima NE PRETHODI kombinacija od tri cifre koja se završava kosom crtom).

(U praksi, navedeni regularni izraz mogao bi se iskoristiti za pronalaženje nepravilno formatiranih brojeva telefona.)

Za kraj ....

Operatori koje smo ukratko opisali u ovom članku predstavljaju veoma korisnu dopunu u odnosu na operatore o kojima smo već diskutovali u uvodnom članku, čime je (u praktičnom smislu), uvod u tematiku regularnih izraza zaokružen.

Pravu vrednost (da ponovimo), regularni izrazi pokazuju onda kada počnete da ih koristite u svakodnevnom radu sa editorima, ili, još bolje - u programima koje pišete - i upravo će upotreba regularnih izraza u programskim jezicima biti tema nekih od budućih članaka ....

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 - Kako pronaći unutrašnji sadržaj HTML elemenata
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