Išnagrinėkite pažangų JavaScript šablonų atitikimą naudojant reguliariąsias išraiškas. Sužinokite apie regex sintaksę, praktinius pritaikymus ir optimizavimo metodus efektyviam ir patikimam kodui.
JavaScript Šablonų Atitikimas su Reguliariosiomis Išraiškomis: Išsamus Vadovas
Reguliariosios išraiškos (regex) yra galingas įrankis šablonų atitikimui ir teksto manipuliavimui JavaScript kalboje. Jos leidžia programuotojams ieškoti, tikrinti ir transformuoti eilutes remiantis apibrėžtais šablonais. Šis vadovas pateikia išsamią reguliariųjų išraiškų JavaScript kalboje apžvalgą, apimančią sintaksę, naudojimą ir pažangias technikas.
Kas yra Reguliariosios Išraiškos?
Reguliarioji išraiška yra simbolių seka, kuri apibrėžia paieškos šabloną. Šie šablonai naudojami eilutėms atitikti ir manipuliuoti. Reguliariosios išraiškos plačiai naudojamos programavime tokioms užduotims kaip:
- Duomenų Validavimas: Užtikrinimas, kad vartotojo įvestis atitinka specifinius formatus (pvz., el. pašto adresus, telefono numerius).
- Duomenų Išgavimas: Specifinės informacijos gavimas iš teksto (pvz., datų, URL adresų ar kainų išgavimas).
- Paieška ir Pakeitimas: Teksto radimas ir pakeitimas remiantis sudėtingais šablonais.
- Teksto Apdorojimas: Eilučių skaidymas, sujungimas ar transformavimas remiantis apibrėžtomis taisyklėmis.
Reguliariųjų Išraiškų Kūrimas JavaScript Kalboje
JavaScript kalboje reguliariosios išraiškos gali būti sukurtos dviem būdais:
- Naudojant reguliariosios išraiškos literalą: Apgaubkite šabloną pasviraisiais brūkšniais (
/). - Naudojant
RegExpkonstruktorių: SukurkiteRegExpobjektą, pateikdami šabloną kaip eilutę.
Pavyzdys:
// Naudojant reguliariosios išraiškos literalą
const regexLiteral = /hello/;
// Naudojant RegExp konstruktorių
const regexConstructor = new RegExp("hello");
Pasirinkimas tarp šių dviejų metodų priklauso nuo to, ar šablonas yra žinomas kompiliavimo metu, ar generuojamas dinamiškai. Naudokite literalo žymėjimą, kai šablonas yra fiksuotas ir žinomas iš anksto. Naudokite konstruktorių, kai šabloną reikia sukurti programiškai, ypač kai įtraukiami kintamieji.
Pagrindinė Regex Sintaksė
Reguliariosios išraiškos susideda iš simbolių, kurie atspindi šabloną, kurį reikia atitikti. Štai keletas pagrindinių regex komponentų:
- Pažodiniai Simboliai: Atitinka pačius simbolius (pvz.,
/a/atitinka simbolį 'a'). - Metasimboliai: Turi specialias reikšmes (pvz.,
.,^,$,*,+,?,[],{},(),\,|). - Simbolių Klasės: Atspindi simbolių rinkinius (pvz.,
[abc]atitinka 'a', 'b' arba 'c'). - Kvantifikatoriai: Nurodo, kiek kartų simbolis ar grupė turėtų pasikartoti (pvz.,
*,+,?,{n},{n,},{n,m}). - Inkarai: Atitinka pozicijas eilutėje (pvz.,
^atitinka pradžią,$atitinka pabaigą).
Dažniausi Metasimboliai:
.(taškas): Atitinka bet kurį vieną simbolį, išskyrus naujos eilutės simbolį.^(stogelis): Atitinka eilutės pradžią.$(dolerio ženklas): Atitinka eilutės pabaigą.*(žvaigždutė): Atitinka nulį ar daugiau prieš tai einančio simbolio ar grupės pasikartojimų.+(pliusas): Atitinka vieną ar daugiau prieš tai einančio simbolio ar grupės pasikartojimų.?(klaustukas): Atitinka nulį ar vieną prieš tai einančio simbolio ar grupės pasikartojimą. Naudojamas pasirenkamiems simboliams.[](laužtiniai skliaustai): Apibrėžia simbolių klasę, atitinkančią bet kurį vieną simbolį skliaustuose.{}(riestiniai skliaustai): Nurodo pasikartojimų, kuriuos reikia atitikti, skaičių.{n}atitinka lygiai n kartų,{n,}atitinka n ar daugiau kartų,{n,m}atitinka nuo n iki m kartų.()(apvalūs skliaustai): Grupuoja simbolius kartu ir užfiksuoja atitiktą poeilutę.\(atvirkštinis pasvirasis brūkšnys): Ekranuoja metasimbolius, leidžiant juos atitikti pažodžiui.|(vertikalus brūkšnys): Veikia kaip „arba“ operatorius, atitinkantis išraišką prieš jį arba po jo.
Simbolių Klasės:
[abc]: Atitinka bet kurį iš simbolių a, b arba c.[^abc]: Atitinka bet kurį simbolį, kuris *nėra* a, b arba c.[a-z]: Atitinka bet kurią mažąją raidę nuo a iki z.[A-Z]: Atitinka bet kurią didžiąją raidę nuo A iki Z.[0-9]: Atitinka bet kurį skaitmenį nuo 0 iki 9.[a-zA-Z0-9]: Atitinka bet kurį raidinį-skaitinį simbolį.\d: Atitinka bet kurį skaitmenį (atitinka[0-9]).\D: Atitinka bet kurį ne skaitmens simbolį (atitinka[^0-9]).\w: Atitinka bet kurį žodžio simbolį (raidinis-skaitinis simbolis plius pabraukimo brūkšnys; atitinka[a-zA-Z0-9_]).\W: Atitinka bet kurį ne žodžio simbolį (atitinka[^a-zA-Z0-9_]).\s: Atitinka bet kurį tarpo simbolį (tarpas, tabuliacija, nauja eilutė ir t. t.).\S: Atitinka bet kurį ne tarpo simbolį.
Kvantifikatoriai:
*: Atitinka prieš tai einantį elementą nulį ar daugiau kartų. Pavyzdžiui,a*atitinka "", "a", "aa", "aaa" ir t. t.+: Atitinka prieš tai einantį elementą vieną ar daugiau kartų. Pavyzdžiui,a+atitinka "a", "aa", "aaa", bet ne "".?: Atitinka prieš tai einantį elementą nulį ar vieną kartą. Pavyzdžiui,a?atitinka "" arba "a".{n}: Atitinka prieš tai einantį elementą lygiai *n* kartų. Pavyzdžiui,a{3}atitinka "aaa".{n,}: Atitinka prieš tai einantį elementą *n* ar daugiau kartų. Pavyzdžiui,a{2,}atitinka "aa", "aaa", "aaaa" ir t. t.{n,m}: Atitinka prieš tai einantį elementą nuo *n* iki *m* kartų (imtinai). Pavyzdžiui,a{2,4}atitinka "aa", "aaa" arba "aaaa".
Inkarai:
^: Atitinka eilutės pradžią. Pavyzdžiui,^Helloatitinka eilutes, kurios *prasideda* žodžiu "Hello".$: Atitinka eilutės pabaigą. Pavyzdžiui,World$atitinka eilutes, kurios *baigiasi* žodžiu "World".\b: Atitinka žodžio ribą. Tai yra pozicija tarp žodžio simbolio (\w) ir ne žodžio simbolio (\W) arba eilutės pradžios ar pabaigos. Pavyzdžiui,\bword\batitinka visą žodį "word".
Vėliavėlės:
Regex vėliavėlės modifikuoja reguliariųjų išraiškų elgseną. Jos pridedamos prie regex literalo pabaigos arba perduodamos kaip antras argumentas RegExp konstruktoriui.
g(globali): Atitinka visus šablono pasikartojimus, o ne tik pirmąjį.i(ignoruoti raidžių dydį): Atlieka atitikimą nepaisant raidžių dydžio.m(kelių eilučių): Įjungia kelių eilučių režimą, kuriame^ir$atitinka kiekvienos eilutės pradžią ir pabaigą (atskirtų\n).s(dotAll): Leidžia taškui (.) atitikti ir naujos eilutės simbolius.u(unicode): Įjungia pilną Unicode palaikymą.y(lipnus): Atitinka tik nuo indekso, nurodyto regexlastIndexsavybėje.
JavaScript Regex Metodai
JavaScript pateikia kelis metodus darbui su reguliariosiomis išraiškomis:
test(): Patikrina, ar eilutė atitinka šabloną. Grąžinatruearbafalse.exec(): Vykdo paiešką eilutėje. Grąžina masyvą su atitiktu tekstu ir užfiksuotomis grupėmis, arbanull, jei atitikties nerasta.match(): Grąžina masyvą su rezultatais, gautais suderinus eilutę su reguliariaja išraiška. Elgiasi skirtingai sugvėliavėle ir be jos.search(): Ieško atitikties eilutėje. Grąžina pirmo atitikimo indeksą, arba -1, jei atitikties nerasta.replace(): Pakeičia šablono pasikartojimus pakeitimo eilute arba funkcija, kuri grąžina pakeitimo eilutę.split(): Suskaido eilutę į poeilučių masyvą pagal reguliariąją išraišką.
Pavyzdžiai Naudojant Regex Metodus:
// test()
const regex = /hello/;
const str = "hello world";
console.log(regex.test(str)); // Išvestis: true
// exec()
const regex2 = /hello (\w+)/;
const str2 = "hello world";
const result = regex2.exec(str2);
console.log(result); // Išvestis: ["hello world", "world", index: 0, input: "hello world", groups: undefined]
// match() su 'g' vėliavėle
const regex3 = /\d+/g; // Atitinka vieną ar daugiau skaitmenų globaliai
const str3 = "There are 123 apples and 456 oranges.";
const matches = str3.match(regex3);
console.log(matches); // Išvestis: ["123", "456"]
// match() be 'g' vėliavėlės
const regex4 = /\d+/;
const str4 = "There are 123 apples and 456 oranges.";
const match = str4.match(regex4);
console.log(match); // Išvestis: ["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)); // Išvestis: 6
// replace()
const regex6 = /world/;
const str6 = "hello world";
const newStr = str6.replace(regex6, "JavaScript");
console.log(newStr); // Išvestis: hello JavaScript
// replace() su funkcija
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); // Išvestis: Today's date is 27/10/2023
// split()
const regex8 = /, /;
const str8 = "apple, banana, cherry";
const arr = str8.split(regex8);
console.log(arr); // Išvestis: ["apple", "banana", "cherry"]
Pažangios Regex Technikos
Užfiksuojančios Grupės:
Apvalūs skliaustai () naudojami kuriant užfiksuojančias grupes reguliariosiose išraiškose. Užfiksuotos grupės leidžia išgauti konkrečias atitikto teksto dalis. exec() ir match() metodai grąžina masyvą, kurio pirmasis elementas yra visa atitiktis, o vėlesni elementai yra užfiksuotos grupės.
const regex = /(\d{4})-(\d{2})-(\d{2})/;
const dateString = "2023-10-27";
const match = regex.exec(dateString);
console.log(match[0]); // Išvestis: 2023-10-27 (Visa atitiktis)
console.log(match[1]); // Išvestis: 2023 (Pirmoji užfiksuota grupė - metai)
console.log(match[2]); // Išvestis: 10 (Antroji užfiksuota grupė - mėnuo)
console.log(match[3]); // Išvestis: 27 (Trečioji užfiksuota grupė - diena)
Pavadintos Užfiksuojančios Grupės:
ES2018 pristatė pavadintas užfiksuojančias grupes, kurios leidžia priskirti vardus užfiksuojančioms grupėms naudojant sintaksę (?. Tai daro kodą skaitomesnį ir lengviau prižiūrimą.
const regex = /(?\d{4})-(?\d{2})-(?\d{2})/;
const dateString = "2023-10-27";
const match = regex.exec(dateString);
console.log(match.groups.year); // Išvestis: 2023
console.log(match.groups.month); // Išvestis: 10
console.log(match.groups.day); // Išvestis: 27
Neužfiksuojančios Grupės:
Jei reikia sugrupuoti regex dalis neužfiksuojant jų (pvz., taikant kvantifikatorių grupei), galite naudoti neužfiksuojančią grupę su sintakse (?:...). Taip išvengiama nereikalingo atminties paskirstymo užfiksuotoms grupėms.
const regex = /(?:https?:\/\/)?([\w\.]+)/; // Atitinka URL, bet užfiksuoja tik domeno vardą
const url = "https://www.example.com/path";
const match = regex.exec(url);
console.log(match[1]); // Išvestis: www.example.com
Žvalgymasis (Lookarounds):
Žvalgymasis yra nulinio pločio tvirtinimai, kurie atitinka poziciją eilutėje remiantis šablonu, kuris yra prieš (lookbehind) arba po (lookahead) tos pozicijos, neįtraukiant paties žvalgymosi šablono į atitiktį.
- Teigiamas Žvalgymasis į Priekį (Positive Lookahead):
(?=...)Atitinka, jei šablonas, esantis žvalgymosi viduje, eina *po* dabartinės pozicijos. - Neigiamas Žvalgymasis į Priekį (Negative Lookahead):
(?!...)Atitinka, jei šablonas, esantis žvalgymosi viduje, *neina* po dabartinės pozicijos. - Teigiamas Žvalgymasis Atgal (Positive Lookbehind):
(?<=...)Atitinka, jei šablonas, esantis žvalgymosi viduje, yra *prieš* dabartinę poziciją. - Neigiamas Žvalgymasis Atgal (Negative Lookbehind):
(? Atitinka, jei šablonas, esantis žvalgymosi viduje, *nėra* prieš dabartinę poziciją.
Pavyzdys:
// Teigiamas žvalgymasis į priekį: gauti kainą tik tada, kai po jos eina USD
const regex = /\d+(?= USD)/;
const text = "The price is 100 USD";
const match = text.match(regex);
console.log(match); // Išvestis: ["100"]
// Neigiamas žvalgymasis į priekį: gauti žodį tik tada, kai po jo neina skaičius
const regex2 = /\b\w+\b(?! \d)/;
const text2 = "apple 123 banana orange 456";
const matches = text2.match(regex2);
console.log(matches); // Išvestis: null, nes match() grąžina tik pirmą atitiktį be 'g' vėliavėlės, o tai nėra tai, ko mums reikia.
// norint tai pataisyti:
const regex3 = /\b\w+\b(?! \d)/g;
const text3 = "apple 123 banana orange 456";
const matches3 = text3.match(regex3);
console.log(matches3); // Išvestis: [ 'banana' ]
// Teigiamas žvalgymasis atgal: gauti vertę tik tada, kai prieš ją yra $
const regex4 = /(?<=\$)\d+/;
const text4 = "The price is $200";
const match4 = text4.match(regex4);
console.log(match4); // Išvestis: ["200"]
// Neigiamas žvalgymasis atgal: gauti žodį tik tada, kai prieš jį nėra žodžio 'not'
const regex5 = /(?
Atgalinės Nuorodos (Backreferences):
Atgalinės nuorodos leidžia nurodyti anksčiau užfiksuotas grupes toje pačioje reguliariajoje išraiškoje. Jos naudoja sintaksę \1, \2 ir t. t., kur skaičius atitinka užfiksuotos grupės numerį.
const regex = /([a-z]+) \1/;
const text = "hello hello world";
const match = regex.exec(text);
console.log(match); // Išvestis: ["hello hello", "hello", index: 0, input: "hello hello world", groups: undefined]
Praktiniai Reguliariųjų Išraiškų Pritaikymai
El. Pašto Adresų Validavimas:
Dažnas reguliariųjų išraiškų panaudojimo atvejis yra el. pašto adresų validavimas. Nors tobulas el. pašto validavimo regex yra itin sudėtingas, štai supaprastintas pavyzdys:
const emailRegex = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/;
console.log(emailRegex.test("test@example.com")); // Išvestis: true
console.log(emailRegex.test("invalid-email")); // Išvestis: false
console.log(emailRegex.test("test@sub.example.co.uk")); // Išvestis: true
URL Išgavimas iš Teksto:
Galite naudoti reguliariąsias išraiškas URL adresams išgauti iš teksto bloko:
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); // Išvestis: ["https://www.example.com", "http://blog.example.org"]
CSV Duomenų Analizė (Parsing):
Reguliariosios išraiškos gali būti naudojamos CSV (Comma-Separated Values) duomenims analizuoti. Štai pavyzdys, kaip suskaidyti CSV eilutę į verčių masyvą, atsižvelgiant į laukus su kabutėmis:
const csvString = 'John,Doe,"123, Main St",New York';
const csvRegex = /(?:"([^"]*(?:""[^"]*)*)")|([^,]+)/g; //Pataisytas CSV regex
let values = [];
let match;
while (match = csvRegex.exec(csvString)) {
values.push(match[1] ? match[1].replace(/""/g, '"') : match[2]);
}
console.log(values); // Išvestis: ["John", "Doe", "123, Main St", "New York"]
Tarptautinių Telefono Numerių Validavimas
Tarptautinių telefono numerių validavimas yra sudėtingas dėl skirtingų formatų ir ilgių. Patikimas sprendimas dažnai apima bibliotekos naudojimą, tačiau supaprastintas regex gali suteikti pagrindinį patikrinimą:
const phoneRegex = /^\+(?:[0-9] ?){6,14}[0-9]$/;
console.log(phoneRegex.test("+1 555 123 4567")); // Išvestis: true (JAV pavyzdys)
console.log(phoneRegex.test("+44 20 7946 0500")); // Išvestis: true (JK pavyzdys)
console.log(phoneRegex.test("+81 3 3224 5000")); // Išvestis: true (Japonijos pavyzdys)
console.log(phoneRegex.test("123-456-7890")); // Išvestis: false
Slaptažodžio Stiprumo Validavimas
Reguliariosios išraiškos yra naudingos slaptažodžio stiprumo politikai įgyvendinti. Žemiau pateiktas pavyzdys tikrina minimalų ilgį, didžiąsias ir mažąsias raides bei skaičių.
const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/;
console.log(passwordRegex.test("P@ssword123")); // Išvestis: true
console.log(passwordRegex.test("password")); // Išvestis: false (nėra didžiosios raidės ar skaičiaus)
console.log(passwordRegex.test("Password")); // Išvestis: false (nėra skaičiaus)
console.log(passwordRegex.test("Pass123")); // Išvestis: false (nėra mažosios raidės)
console.log(passwordRegex.test("P@ss1")); // Išvestis: false (mažiau nei 8 simboliai)
Regex Optimizavimo Technikos
Reguliariosios išraiškos gali būti skaičiavimo požiūriu brangios, ypač esant sudėtingiems šablonams ar didelėms įvestims. Štai keletas regex našumo optimizavimo technikų:
- Būkite Konkretūs: Venkite naudoti pernelyg bendrų šablonų, kurie gali atitikti daugiau nei numatyta.
- Naudokite Inkarus: Kai tik įmanoma, pririškite regex prie eilutės pradžios ar pabaigos (
^,$). - Venkite Atgalinio Sekimo (Backtracking): Sumažinkite atgalinį sekimą naudodami posesyvius kvantifikatorius (pvz.,
++vietoj+) arba atomines grupes ((?>...)), kai tinkama. - Kompiliuokite Vieną Kartą: Jei tą patį regex naudojate kelis kartus, kompiliuokite jį vieną kartą ir pakartotinai naudokite
RegExpobjektą. - Išmintingai Naudokite Simbolių Klases: Simbolių klasės (
[]) paprastai yra greitesnės nei alternacijos (|). - Išlaikykite Paprastumą: Venkite pernelyg sudėtingų regex, kuriuos sunku suprasti ir prižiūrėti. Kartais sudėtingos užduoties suskaidymas į kelis paprastesnius regex arba kitų eilučių manipuliavimo technikų naudojimas gali būti efektyvesnis.
Dažniausios Regex Klaidos
- Pamirštama Ekranuoti Metasimbolius: Specialių simbolių, tokių kaip
.,*,+,?,$,^,(,),[,],{,},|ir\, neekranavimas, kai norima juos atitikti pažodžiui. - Pernelyg Dažnas
.(taško) Naudojimas: Taškas atitinka bet kurį simbolį (išskyrus naują eilutę kai kuriuose režimuose), o tai gali lemti netikėtas atitiktis, jei naudojamas neatsargiai. Būkite konkretesni, kai įmanoma, naudodami simbolių klases ar kitus labiau ribojančius šablonus. - Godumas (Greediness): Pagal numatytuosius nustatymus, kvantifikatoriai, tokie kaip
*ir+, yra godūs ir atitiks kuo daugiau. Naudokite tingius kvantifikatorius (*?,+?), kai reikia atitikti trumpiausią įmanomą eilutę. - Neteisingas Inkarų Naudojimas: Neteisingas
^(eilutės/linijos pradžia) ir$(eilutės/linijos pabaiga) elgsenos supratimas gali lemti neteisingą atitikimą. Nepamirškite naudotim(kelių eilučių) vėliavėlės, kai dirbate su kelių eilučių eilutėmis ir norite, kad^ir$atitiktų kiekvienos eilutės pradžią ir pabaigą. - Kraštutinių Atvejų Neapdorojimas: Neatsižvelgimas į visus galimus įvesties scenarijus ir kraštutinius atvejus gali sukelti klaidų. Kruopščiai išbandykite savo regex su įvairiomis įvestimis, įskaitant tuščias eilutes, netinkamus simbolius ir ribines sąlygas.
- Našumo Problemos: Pernelyg sudėtingų ir neefektyvių regex kūrimas gali sukelti našumo problemų, ypač su didelėmis įvestimis. Optimizuokite savo regex naudodami konkretesnius šablonus, vengdami nereikalingo atgalinio sekimo ir kompiliuodami pakartotinai naudojamus regex.
- Simbolių Koduočių Ignoravimas: Netinkamas simbolių koduočių (ypač Unicode) tvarkymas gali lemti netikėtus rezultatus. Naudokite
uvėliavėlę, kai dirbate su Unicode simboliais, kad užtikrintumėte teisingą atitikimą.
Išvada
Reguliariosios išraiškos yra vertingas įrankis šablonų atitikimui ir teksto manipuliavimui JavaScript kalboje. Įvaldę regex sintaksę ir technikas, galėsite efektyviai spręsti platų problemų spektrą – nuo duomenų validavimo iki sudėtingo teksto apdorojimo. Suprasdami šiame vadove aptartas sąvokas ir praktikuodamiesi su realaus pasaulio pavyzdžiais, galite tapti įgudusiu reguliariųjų išraiškų naudotoju ir pagerinti savo JavaScript programavimo įgūdžius.
Atminkite, kad reguliariosios išraiškos gali būti sudėtingos, ir dažnai naudinga jas kruopščiai išbandyti naudojant internetinius regex testuotojus, tokius kaip regex101.com ar regexr.com. Tai leidžia vizualizuoti atitiktis ir efektyviai derinti bet kokias problemas. Sėkmingo programavimo!