Istražite napredno JavaScript usporeÄivanje uzoraka pomoÄu regularnih izraza. NauÄite o regex sintaksi, praktiÄnim primjenama i tehnikama optimizacije za efikasan i robustan kod.
JavaScript UsporeÄivanje Uzoraka s Regularnim Izrazima: Sveobuhvatan VodiÄ
Regularni izrazi (regex) moÄan su alat za usporeÄivanje uzoraka i manipulaciju tekstom u JavaScriptu. OmoguÄuju programerima pretraživanje, validaciju i transformaciju stringova na temelju definiranih uzoraka. Ovaj vodiÄ pruža sveobuhvatan pregled regularnih izraza u JavaScriptu, pokrivajuÄi sintaksu, upotrebu i napredne tehnike.
Å to su regularni izrazi?
Regularni izraz je slijed znakova koji definira uzorak pretraživanja. Ti se uzorci koriste za usporeÄivanje i manipulaciju stringovima. Regularni izrazi se Å”iroko koriste u programiranju za zadatke kao Å”to su:
- Validacija podataka: Osiguravanje da korisniÄki unos odgovara odreÄenim formatima (npr. e-mail adrese, telefonski brojevi).
- Ekstrakcija podataka: DohvaÄanje specifiÄnih informacija iz teksta (npr. izdvajanje datuma, URL-ova ili cijena).
- Pretraživanje i zamjena: Pronalaženje i zamjena teksta na temelju složenih uzoraka.
- Obrada teksta: Dijeljenje, spajanje ili transformacija stringova na temelju definiranih pravila.
Stvaranje regularnih izraza u JavaScriptu
U JavaScriptu se regularni izrazi mogu stvoriti na dva naÄina:
- KoriÅ”tenjem literala regularnog izraza: Umetnite uzorak izmeÄu kosih crta (
/). - KoriŔtenjem
RegExpkonstruktora: StvoriteRegExpobjekt s uzorkom kao stringom.
Primjer:
// KoriŔtenje literala regularnog izraza
const regexLiteral = /hello/;
// KoriŔtenje RegExp konstruktora
const regexConstructor = new RegExp("hello");
Izbor izmeÄu ove dvije metode ovisi o tome je li uzorak poznat u vrijeme kompajliranja ili se dinamiÄki generira. Koristite literalnu notaciju kada je uzorak fiksan i poznat unaprijed. Koristite konstruktor kada uzorak treba programski izgraditi, posebno kada ukljuÄuje varijable.
Osnovna Regex Sintaksa
Regularni izrazi sastoje se od znakova koji predstavljaju uzorak koji treba uskladiti. Evo nekih temeljnih regex komponenti:
- Literalni znakovi: UsporeÄuju same znakove (npr.
/a/usporeÄuje znak 'a'). - Meta-znakovi: Imaju posebna znaÄenja (npr.
.,^,$,*,+,?,[],{},(),\,|). - Klase znakova: Predstavljaju skupove znakova (npr.
[abc]usporeÄuje 'a', 'b' ili 'c'). - Kvantifikatori: OdreÄuju koliko puta se znak ili grupa treba pojaviti (npr.
*,+,?,{n},{n,},{n,m}). - Sidra: UsporeÄuju pozicije u stringu (npr.
^usporeÄuje poÄetak,$usporeÄuje kraj).
UobiÄajeni meta-znakovi:
.(toÄka): UsporeÄuje bilo koji pojedinaÄni znak osim novog retka.^(caret): UsporeÄuje poÄetak stringa.$(dolar): UsporeÄuje kraj stringa.*(zvjezdica): UsporeÄuje nula ili viÅ”e pojavljivanja prethodnog znaka ili grupe.+(plus): UsporeÄuje jedno ili viÅ”e pojavljivanja prethodnog znaka ili grupe.?(upitnik): UsporeÄuje nula ili jedno pojavljivanje prethodnog znaka ili grupe. Koristi se za opcionalne znakove.[](uglate zagrade): Definira klasu znakova, usporeÄujuÄi bilo koji pojedinaÄni znak unutar zagrada.{}(vitiÄaste zagrade): OdreÄuje broj pojavljivanja za usporedbu.{n}usporeÄuje toÄno n puta,{n,}usporeÄuje n ili viÅ”e puta,{n,m}usporeÄuje izmeÄu n i m puta.()(okrugle zagrade): Grupiraju znakove i hvataju usporeÄeni podstring.\(obrnuta kosa crta): Escapira meta-znakove, omoguÄujuÄi vam da ih usporedite doslovno.|(cijev): Djeluje kao "ili" operator, usporeÄujuÄi izraz prije ili poslije njega.
Klase znakova:
[abc]: UsporeÄuje bilo koji od znakova a, b ili c.[^abc]: UsporeÄuje bilo koji znak koji *nije* a, b ili c.[a-z]: UsporeÄuje bilo koje malo slovo od a do z.[A-Z]: UsporeÄuje bilo koje veliko slovo od A do Z.[0-9]: UsporeÄuje bilo koju znamenku od 0 do 9.[a-zA-Z0-9]: UsporeÄuje bilo koji alfanumeriÄki znak.\d: UsporeÄuje bilo koju znamenku (ekvivalentno[0-9]).\D: UsporeÄuje bilo koji znak koji nije znamenka (ekvivalentno[^0-9]).\w: UsporeÄuje bilo koji znak rijeÄi (alfanumeriÄki plus donja crta; ekvivalentno[a-zA-Z0-9_]).\W: UsporeÄuje bilo koji znak koji nije znak rijeÄi (ekvivalentno[^a-zA-Z0-9_]).\s: UsporeÄuje bilo koji znak praznine (razmak, tabulator, novi redak, itd.).\S: UsporeÄuje bilo koji znak koji nije praznina.
Kvantifikatori:
*: UsporeÄuje prethodni element nula ili viÅ”e puta. Na primjer,a*usporeÄuje "", "a", "aa", "aaa" i tako dalje.+: UsporeÄuje prethodni element jedan ili viÅ”e puta. Na primjer,a+usporeÄuje "a", "aa", "aaa", ali ne "".?: UsporeÄuje prethodni element nula ili jedan put. Na primjer,a?usporeÄuje "" ili "a".{n}: UsporeÄuje prethodni element toÄno *n* puta. Na primjer,a{3}usporeÄuje "aaa".{n,}: UsporeÄuje prethodni element *n* ili viÅ”e puta. Na primjer,a{2,}usporeÄuje "aa", "aaa", "aaaa" i tako dalje.{n,m}: UsporeÄuje prethodni element izmeÄu *n* i *m* puta (ukljuÄivo). Na primjer,a{2,4}usporeÄuje "aa", "aaa" ili "aaaa".
Sidra:
^: UsporeÄuje poÄetak stringa. Na primjer,^HellousporeÄuje stringove koji *poÄinju* s "Hello".$: UsporeÄuje kraj stringa. Na primjer,World$usporeÄuje stringove koji *zavrÅ”avaju* s "World".\b: UsporeÄuje granicu rijeÄi. Ovo je pozicija izmeÄu znaka rijeÄi (\w) i znaka koji nije rijeÄ (\W) ili poÄetka ili kraja stringa. Na primjer,\bword\busporeÄuje cijelu rijeÄ "word".
Zastavice (Flags):
Regex zastavice mijenjaju ponaÅ”anje regularnih izraza. Dodaju se na kraj regex literala ili se prosljeÄuju kao drugi argument RegExp konstruktoru.
g(global): UsporeÄuje sva pojavljivanja uzorka, a ne samo prvo.i(ignore case): Obavlja usporedbu neovisnu o velikim i malim slovima.m(multiline): OmoguÄuje viÅ”elinijski naÄin rada, gdje^i$usporeÄuju poÄetak i kraj svakog retka (odvojenog s\n).s(dotAll): OmoguÄuje toÄki (.) da usporeÄuje i znakove novog retka.u(unicode): OmoguÄuje punu Unicode podrÅ”ku.y(sticky): UsporeÄuje samo od indeksa koji je naveden ulastIndexsvojstvu regexa.
JavaScript Regex Metode
JavaScript pruža nekoliko metoda za rad s regularnim izrazima:
test(): Testira podudara li se string s uzorkom. VraÄatrueilifalse.exec(): IzvrÅ”ava pretragu za podudaranjem u stringu. VraÄa polje koje sadrži podudarni tekst i uhvaÄene grupe, ilinullako podudaranje nije pronaÄeno.match(): VraÄa polje koje sadrži rezultate podudaranja stringa s regularnim izrazom. PonaÅ”a se razliÄito sa i bezgzastavice.search(): Testira podudaranje u stringu. VraÄa indeks prvog podudaranja, ili -1 ako podudaranje nije pronaÄeno.replace(): Zamjenjuje pojavljivanja uzorka zamjenskim stringom ili funkcijom koja vraÄa zamjenski string.split(): Dijeli string u polje podstringova na temelju regularnog izraza.
Primjeri koriŔtenja Regex metoda:
// test()
const regex = /hello/;
const str = "hello world";
console.log(regex.test(str)); // Izlaz: true
// exec()
const regex2 = /hello (\w+)/;
const str2 = "hello world";
const result = regex2.exec(str2);
console.log(result); // Izlaz: ["hello world", "world", index: 0, input: "hello world", groups: undefined]
// match() s 'g' zastavicom
const regex3 = /\d+/g; // UsporeÄuje jednu ili viÅ”e znamenki globalno
const str3 = "There are 123 apples and 456 oranges.";
const matches = str3.match(regex3);
console.log(matches); // Izlaz: ["123", "456"]
// match() bez 'g' zastavice
const regex4 = /\d+/;
const str4 = "There are 123 apples and 456 oranges.";
const match = str4.match(regex4);
console.log(match); // Izlaz: ["123", index: 11, input: "There are 123 apples and 456 oranges.", groups: undefined]
// search()
const regex5 = /world/;
const str5 = "hello world";
console.log(str5.search(regex5)); // Izlaz: 6
// replace()
const regex6 = /world/;
const str6 = "hello world";
const newStr = str6.replace(regex6, "JavaScript");
console.log(newStr); // Izlaz: hello JavaScript
// replace() s funkcijom
const regex7 = /(\d+)-(\d+)-(\d+)/;
const str7 = "Today's date is 2023-10-27";
const newStr2 = str7.replace(regex7, (match, year, month, day) => {
return `${day}/${month}/${year}`;
});
console.log(newStr2); // Izlaz: Today's date is 27/10/2023
// split()
const regex8 = /, /;
const str8 = "apple, banana, cherry";
const arr = str8.split(regex8);
console.log(arr); // Izlaz: ["apple", "banana", "cherry"]
Napredne Regex Tehnike
Grupe za hvatanje (Capturing Groups):
Okrugle zagrade () koriste se za stvaranje grupa za hvatanje u regularnim izrazima. UhvaÄene grupe omoguÄuju vam izdvajanje specifiÄnih dijelova podudarnog teksta. Metode exec() i match() vraÄaju polje gdje je prvi element cijelo podudaranje, a sljedeÄi elementi su uhvaÄene grupe.
const regex = /(\d{4})-(\d{2})-(\d{2})/;
const dateString = "2023-10-27";
const match = regex.exec(dateString);
console.log(match[0]); // Izlaz: 2023-10-27 (Cijelo podudaranje)
console.log(match[1]); // Izlaz: 2023 (Prva uhvaÄena grupa - godina)
console.log(match[2]); // Izlaz: 10 (Druga uhvaÄena grupa - mjesec)
console.log(match[3]); // Izlaz: 27 (TreÄa uhvaÄena grupa - dan)
Imenovane grupe za hvatanje (Named Capturing Groups):
ES2018 je uveo imenovane grupe za hvatanje, koje vam omoguÄuju dodjeljivanje imena grupama za hvatanje koristeÄi sintaksu (?. To Äini kod Äitljivijim i lakÅ”im za održavanje.
const regex = /(?\d{4})-(?\d{2})-(?\d{2})/;
const dateString = "2023-10-27";
const match = regex.exec(dateString);
console.log(match.groups.year); // Izlaz: 2023
console.log(match.groups.month); // Izlaz: 10
console.log(match.groups.day); // Izlaz: 27
Grupe koje ne hvataju (Non-Capturing Groups):
Ako trebate grupirati dijelove regexa bez njihovog hvatanja (npr. za primjenu kvantifikatora na grupu), možete koristiti grupu koja ne hvata sa sintaksom (?:...). To izbjegava nepotrebnu alokaciju memorije za uhvaÄene grupe.
const regex = /(?:https?:\/\/)?([\w\.]+)/; // UsporeÄuje URL, ali hvata samo naziv domene
const url = "https://www.example.com/path";
const match = regex.exec(url);
console.log(match[1]); // Izlaz: www.example.com
Lookarounds:
Lookarounds su tvrdnje nulte Å”irine koje usporeÄuju poziciju u stringu na temelju uzorka koji prethodi (lookbehind) ili slijedi (lookahead) toj poziciji, bez ukljuÄivanja samog lookaround uzorka u podudaranje.
- Pozitivni Lookahead:
(?=...)UsporeÄuje ako uzorak unutar lookaheada *slijedi* trenutnu poziciju. - Negativni Lookahead:
(?!...)UsporeÄuje ako uzorak unutar lookaheada *ne slijedi* trenutnu poziciju. - Pozitivni Lookbehind:
(?<=...)UsporeÄuje ako uzorak unutar lookbehinda *prethodi* trenutnoj poziciji. - Negativni Lookbehind:
(? UsporeÄuje ako uzorak unutar lookbehinda *ne prethodi* trenutnoj poziciji.
Primjer:
// Pozitivni Lookahead: Dohvati cijenu samo ako je slijedi USD
const regex = /\d+(?= USD)/;
const text = "The price is 100 USD";
const match = text.match(regex);
console.log(match); // Izlaz: ["100"]
// Negativni Lookahead: Dohvati rijeÄ samo ako je ne slijedi broj
const regex2 = /\b\w+\b(?! \d)/;
const text2 = "apple 123 banana orange 456";
const matches = text2.match(regex2);
console.log(matches); // Izlaz: null jer match() vraÄa samo prvo podudaranje bez 'g' zastavice, Å”to nije ono Å”to trebamo.
// da to popravimo:
const regex3 = /\b\w+\b(?! \d)/g;
const text3 = "apple 123 banana orange 456";
const matches3 = text3.match(regex3);
console.log(matches3); // Izlaz: [ 'banana' ]
// Pozitivni Lookbehind: Dohvati vrijednost samo ako joj prethodi $
const regex4 = /(?<=\$)\d+/;
const text4 = "The price is $200";
const match4 = text4.match(regex4);
console.log(match4); // Izlaz: ["200"]
// Negativni Lookbehind: Dohvati rijeÄ samo ako joj ne prethodi rijeÄ 'not'
const regex5 = /(?
Povratne reference (Backreferences):
Povratne reference omoguÄuju vam da se pozovete na prethodno uhvaÄene grupe unutar istog regularnog izraza. Koriste sintaksu \1, \2, itd., gdje broj odgovara broju uhvaÄene grupe.
const regex = /([a-z]+) \1/;
const text = "hello hello world";
const match = regex.exec(text);
console.log(match); // Izlaz: ["hello hello", "hello", index: 0, input: "hello hello world", groups: undefined]
PraktiÄne primjene regularnih izraza
Validacija e-mail adresa:
UobiÄajen sluÄaj upotrebe regularnih izraza je validacija e-mail adresa. Iako je savrÅ”en regex za validaciju e-poÅ”te izuzetno složen, evo pojednostavljenog primjera:
const emailRegex = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/;
console.log(emailRegex.test("test@example.com")); // Izlaz: true
console.log(emailRegex.test("invalid-email")); // Izlaz: false
console.log(emailRegex.test("test@sub.example.co.uk")); // Izlaz: true
Izdvajanje URL-ova iz teksta:
Možete koristiti regularne izraze za izdvajanje URL-ova iz bloka teksta:
const urlRegex = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g;
const text = "Visit our website at https://www.example.com or check out http://blog.example.org.";
const urls = text.match(urlRegex);
console.log(urls); // Izlaz: ["https://www.example.com", "http://blog.example.org"]
Parsiranje CSV podataka:
Regularni izrazi mogu se koristiti za parsiranje CSV (Comma-Separated Values) podataka. Evo primjera dijeljenja CSV stringa u polje vrijednosti, uz rukovanje poljima pod navodnicima:
const csvString = 'John,Doe,"123, Main St",New York';
const csvRegex = /(?:"([^"]*(?:""[^"]*)*)")|([^,]+)/g; //Ispravljen CSV regex
let values = [];
let match;
while (match = csvRegex.exec(csvString)) {
values.push(match[1] ? match[1].replace(/""/g, '"') : match[2]);
}
console.log(values); // Izlaz: ["John", "Doe", "123, Main St", "New York"]
Validacija meÄunarodnog telefonskog broja
Validacija meÄunarodnih telefonskih brojeva složena je zbog razliÄitih formata i duljina. Robusno rjeÅ”enje Äesto ukljuÄuje koriÅ”tenje biblioteke, ali pojednostavljeni regex može pružiti osnovnu validaciju:
const phoneRegex = /^\+(?:[0-9] ?){6,14}[0-9]$/;
console.log(phoneRegex.test("+1 555 123 4567")); // Izlaz: true (Primjer iz SAD-a)
console.log(phoneRegex.test("+44 20 7946 0500")); // Izlaz: true (Primjer iz UK)
console.log(phoneRegex.test("+81 3 3224 5000")); // Izlaz: true (Primjer iz Japana)
console.log(phoneRegex.test("123-456-7890")); // Izlaz: false
Validacija jaÄine lozinke
Regularni izrazi korisni su za provoÄenje pravila o jaÄini lozinke. Primjer u nastavku provjerava minimalnu duljinu, velika slova, mala slova i broj.
const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/;
console.log(passwordRegex.test("P@ssword123")); // Izlaz: true
console.log(passwordRegex.test("password")); // Izlaz: false (nema velikog slova ni broja)
console.log(passwordRegex.test("Password")); // Izlaz: false (nema broja)
console.log(passwordRegex.test("Pass123")); // Izlaz: false (nema malog slova)
console.log(passwordRegex.test("P@ss1")); // Izlaz: false (manje od 8 znakova)
Tehnike optimizacije Regexa
Regularni izrazi mogu biti raÄunski skupi, posebno za složene uzorke ili velike unose. Evo nekoliko tehnika za optimizaciju performansi regexa:
- Budite specifiÄni: Izbjegavajte koriÅ”tenje preopÄenitih uzoraka koji mogu odgovarati viÅ”e nego Å”to je namijenjeno.
- Koristite sidra: Sidrite regex na poÄetak ili kraj stringa kad god je to moguÄe (
^,$). - Izbjegavajte backtracking: Smanjite backtracking koriŔtenjem posesivnih kvantifikatora (npr.
++umjesto+) ili atomskih grupa ((?>...)) kada je to prikladno. - Kompajlirajte jednom: Ako koristite isti regex viŔe puta, kompajlirajte ga jednom i ponovno koristite
RegExpobjekt. - Koristite klase znakova mudro: Klase znakova (
[]) opÄenito su brže od alternacija (|). - Neka bude jednostavno: Izbjegavajte pretjerano složene regexe koje je teÅ”ko razumjeti i održavati. Ponekad, razbijanje složenog zadatka na viÅ”e jednostavnijih regexa ili koriÅ”tenje drugih tehnika manipulacije stringovima može biti uÄinkovitije.
UobiÄajene pogreÅ”ke s Regexom
- Zaboravljanje escapiranja meta-znakova: Neuspjeh u escapiranju posebnih znakova poput
.,*,+,?,$,^,(,),[,],{,},|i\kada ih želite doslovno usporediti. - Prekomjerna upotreba
.(toÄke): ToÄka odgovara bilo kojem znaku (osim novog retka u nekim naÄinima), Å”to može dovesti do neoÄekivanih podudaranja ako se ne koristi pažljivo. Budite specifiÄniji kada je to moguÄe koristeÄi klase znakova ili druge restriktivnije uzorke. - Pohlepa (Greediness): Po zadanom, kvantifikatori poput
*i+su pohlepni i pokuÅ”at Äe uskladiti Å”to je viÅ”e moguÄe. Koristite lijene kvantifikatore (*?,+?) kada trebate uskladiti najkraÄi moguÄi string. - NetoÄna upotreba sidara: Nerazumijevanje ponaÅ”anja
^(poÄetak stringa/retka) i$(kraj stringa/retka) može dovesti do netoÄnog podudaranja. Ne zaboravite koristitim(multiline) zastavicu kada radite s viÅ”elinijskim stringovima i želite da^i$odgovaraju poÄetku i kraju svakog retka. - Ne rjeÅ”avanje rubnih sluÄajeva: Neuspjeh u razmatranju svih moguÄih scenarija unosa i rubnih sluÄajeva može dovesti do bugova. Temeljito testirajte svoje regexe s razliÄitim unosima, ukljuÄujuÄi prazne stringove, nevažeÄe znakove i graniÄne uvjete.
- Problemi s performansama: Stvaranje pretjerano složenih i neuÄinkovitih regexa može uzrokovati probleme s performansama, posebno s velikim unosima. Optimizirajte svoje regexe koriÅ”tenjem specifiÄnijih uzoraka, izbjegavanjem nepotrebnog backtrackinga i kompajliranjem regexa koji se koriste viÅ”e puta.
- Ignoriranje kodiranja znakova: Nepravilno rukovanje kodiranjem znakova (posebno Unicode) može dovesti do neoÄekivanih rezultata. Koristite
uzastavicu kada radite s Unicode znakovima kako biste osigurali ispravno podudaranje.
ZakljuÄak
Regularni izrazi su vrijedan alat za usporeÄivanje uzoraka i manipulaciju tekstom u JavaScriptu. Ovladavanje regex sintaksom i tehnikama omoguÄuje vam uÄinkovito rjeÅ”avanje Å”irokog spektra problema, od validacije podataka do složene obrade teksta. Razumijevanjem koncepata o kojima se raspravljalo u ovom vodiÄu i vježbanjem na primjerima iz stvarnog svijeta, možete postati vjeÅ”ti u koriÅ”tenju regularnih izraza za poboljÅ”anje svojih vjeÅ”tina razvoja u JavaScriptu.
Zapamtite da regularni izrazi mogu biti složeni, i Äesto je korisno temeljito ih testirati pomoÄu online regex testera kao Å”to su regex101.com ili regexr.com. To vam omoguÄuje vizualizaciju podudaranja i uÄinkovito otklanjanje bilo kakvih problema. Sretno kodiranje!