Naqshning bir qismi qavslar (...) ichiga olinishi mumkin. Bu âushlash guruhiâ deb ataladi.
Buning ikkita taâsiri bor:
- Moslikning bir qismini natijalar massivida alohida element sifatida olish imkonini beradi.
- Agar qavslardan keyin miqdorchi qoâysak, u butun qavslar guruhi uchun qoâllaniladi.
Misollar
Qavslar qanday ishlashini misollarda koâraylik.
Misol: gogogo
Qavslarsiz go+ naqshi g belgisini, keyin bir yoki koâp marta takrorlangan o ni bildiradi. Masalan, goooo yoki gooooooooo.
Qavslar belgilarni birlashtirib guruhlaydi, shuning uchun (go)+ go, gogo, gogogo va hokazolarni bildiradi.
alert( 'Gogogo now!'.match(/(go)+/ig) ); // "Gogogo"
Misol: domen
Keling, murakkabroq narsa yasaylik â veb-sayt domenini qidiruvchi doimiy ifoda.
Masalan:
mail.com
users.mail.com
smith.users.mail.com
Koârib turganingizdek, domen takrorlanuvchi soâzlardan iborat, oxirgisidan tashqari har biridan keyin nuqta.
Doimiy ifodalarda bu (\w+\.)+\w+:
let regexp = /(\w+\.)+\w+/g;
alert( "site.com my.site.com".match(regexp) ); // site.com,my.site.com
Qidiruv ishlaydi, lekin naqsh tire bilan domenga mos kelmaydi, masalan my-site.com, chunki tire \w sinfiga tegishli emas.
Buni oxirgisidan tashqari har bir soâzda \w ni [\w-] bilan almashtirish orqali tuzatishimiz mumkin: ([\w-]+\.)+\w+.
Misol: email
Oldingi misolni kengaytirish mumkin. Unga asoslanib emaillar uchun doimiy ifoda yaratishimiz mumkin.
Email formati: name@domain. Har qanday soâz nom boâlishi mumkin, tireler va nuqtalar ruxsat etiladi. Doimiy ifodalarda bu [-.\w]+.
Naqsh:
let regexp = /[-.\w]+@([\w-]+\.)+[\w-]+/g;
alert("[email protected] @ [email protected]".match(regexp)); // [email protected], [email protected]
Bu regexp mukammal emas, lekin asosan ishlaydi va tasodifiy xatolarni tuzatishga yordam beradi. Email uchun yagona ishonchli tekshiruv faqat xat yuborish orqali amalga oshirilishi mumkin.
Mosliklarda qavslar mazmuni
Qavslar chapdan oângga raqamlanadi. Qidiruv dvigateli ularning har birига mos kelgan mazmunni eslab qoladi va natijada olish imkonini beradi.
str.match(regexp) metodi, agar regexpda g bayrogâi boâlmasa, birinchi moslikni qidiradi va uni massiv koârinishida qaytaradi:
0indeksida: toâliq moslik.1indeksida: birinchi qavslar mazmuni.2indeksida: ikkinchi qavslar mazmuni.- â¦va hokazoâ¦
Masalan, biz HTML teglarini <.*?> topmoqchimiz va ularni qayta ishlamoqchimiz. Teg mazmuni (burchaklar ichidagi narsa)ni alohida oâzgaruvchida boâlishi qulay boâlardi.
Ichki mazmunni qavslarga oâraylik: <(.*?)>.
Endi biz natijalar massivida ham butun teg <h1> ham uning mazmuni h1 ni olamiz:
let str = '<h1>Hello, world!</h1>';
let tag = str.match(/<(.*?)>/);
alert( tag[0] ); // <h1>
alert( tag[1] ); // h1
Ichki guruhlar
Qavslar ichma-ich boâlishi mumkin. Bu holda raqamlash ham chapdan oângga boradi.
Masalan, <span class="my"> da tegni qidirishda bizni qiziqtirishi mumkin:
- Butun teg mazmuni:
span class="my". - Teg nomi:
span. - Teg atributlari:
class="my".
Ular uchun qavslar qoâshaylik: <(([a-z]+)\s*([^>]*))>.
Ular qanday raqamlanishi (chapdan oângga, ochuvchi qavs boâyicha):
Amalda:
let str = '<span class="my">';
let regexp = /<(([a-z]+)\s*([^>]*))>/;
let result = str.match(regexp);
alert(result[0]); // <span class="my">
alert(result[1]); // span class="my"
alert(result[2]); // span
alert(result[3]); // class="my"
result ning nol indeksi har doim toâliq moslikni saqlaydi.
Keyin chapdan oângga ochuvchi qavs boâyicha raqamlangan guruhlar. Birinchi guruh result[1] sifatida qaytariladi. Bu yerda u butun teg mazmunini oârab oladi.
Keyin result[2] da ikkinchi ochuvchi qavs ([a-z]+) dan guruh â teg nomi, keyin result[3] da teg: ([^>]*).
Satrdagi har bir guruh mazmuni:
Ixtiyoriy guruhlar
Agar guruh ixtiyoriy boâlsa va moslikda mavjud boâlmasa (masalan, (...)? miqdorchisiga ega), tegishli result massiv elementi mavjud va undefined ga teng.
Masalan, a(z)?(c)? regexpni koârib chiqaylik. U "a" ni, ixtiyoriy ravishda "z" keyin, ixtiyoriy ravishda "c" keyin qidiradi.
Agar uni bitta harf a bilan satrda ishga tushirsak, natija:
let match = 'a'.match(/a(z)?(c)?/);
alert( match.length ); // 3
alert( match[0] ); // a (to'liq moslik)
alert( match[1] ); // undefined
alert( match[2] ); // undefined
Massiv uzunligi 3, lekin barcha guruhlar boâsh.
Va ac satr uchun murakkabroq moslik:
let match = 'ac'.match(/a(z)?(c)?/)
alert( match.length ); // 3
alert( match[0] ); // ac (to'liq moslik)
alert( match[1] ); // undefined, chunki (z)? uchun hech narsa yo'q
alert( match[2] ); // c
Massiv uzunligi doimiy: 3. Lekin (z)? guruhi uchun hech narsa yoâq, shuning uchun natija ["ac", undefined, "c"].
Guruhlar bilan barcha mosliklarni qidirish: matchAll
matchAll yangi metod, polyfill kerak boâlishi mumkinmatchAll metodi eski brauzerlarda qoâllab-quvvatlanmaydi.
Polyfill kerak boâlishi mumkin, masalan https://github.com/ljharb/String.prototype.matchAll.
Barcha mosliklarni qidirishda (g bayrogâi), match metodi guruhlar uchun mazmunni qaytarmaydi.
Masalan, satrdagi barcha teglarni topaylik:
let str = '<h1> <h2>';
let tags = str.match(/<(.*?)>/g);
alert( tags ); // <h1>,<h2>
Natija mosliklar massivi, lekin ularning har biri haqida tafsilot yoâq. Lekin amalda biz odatda natijada ushlash guruhlarining mazmuniga muhtojmiz.
Ularni olish uchun str.matchAll(regexp) metodidan foydalanishimiz kerak.
U JavaScript tiliga matchdan ancha keyin, uning âyangi va yaxshilangan versiyasiâ sifatida qoâshildi.
match kabi u mosliklarni qidiradi, lekin 3 ta farq bor:
- U massiv emas, balki iteratsiya qilinadigan obyekt qaytaradi.
gbayrogâi mavjud boâlganda, u har bir moslikni guruhlar bilan massiv sifatida qaytaradi.- Agar moslik boâlmasa,
nullemas, balki boâsh iteratsiya qilinadigan obyekt qaytaradi.
Masalan:
let results = '<h1> <h2>'.matchAll(/<(.*?)>/gi);
// results - massiv emas, balki iteratsiya qilinadigan obyekt
alert(results); // [object RegExp String Iterator]
alert(results[0]); // undefined (*)
results = Array.from(results); // uni massivga aylantiraylik
alert(results[0]); // <h1>,h1 (1-teg)
alert(results[1]); // <h2>,h2 (2-teg)
Koârib turganingizdek, birinchi farq juda muhim, (*) satrida koârsatilganidek. Biz moslikni results[0] sifatida ola olmaymiz, chunki bu obyekt psevdo-massiv emas. Uni Array.from yordamida haqiqiy Array ga aylantirish mumkin. Psevdo-massivlar va iteratsiya qilinadigan obyektlar haqida koâproq maâlumot Tsiklda koârib chiqish imokniyatiga ega maâlumot turlari maqolasida.
Agar natijalarni aylantirayotgan boâlsak, Array.from ga ehtiyoj yoâq:
let results = '<h1> <h2>'.matchAll(/<(.*?)>/gi);
for(let result of results) {
alert(result);
// birinchi alert: <h1>,h1
// ikkinchi: <h2>,h2
}
â¦Yoki destrukturizatsiya yordamida:
let [tag1, tag2] = '<h1> <h2>'.matchAll(/<(.*?)>/gi);
matchAll tomonidan qaytarilgan har bir moslik g bayrogâisiz match tomonidan qaytarilgan format bilan bir xil: bu qoâshimcha index (satrdagi moslik indeksi) va input (manba satr) xususiyatlari bilan massiv:
let results = '<h1> <h2>'.matchAll(/<(.*?)>/gi);
let [tag1, tag2] = results;
alert( tag1[0] ); // <h1>
alert( tag1[1] ); // h1
alert( tag1.index ); // 0
alert( tag1.input ); // <h1> <h2>
matchAll natijasi massiv emas, balki iteratsiya qilinadigan obyekt?Metod nima uchun shunday yaratilgan? Sabab oddiy â optimallashtirish uchun.
matchAll ga chaqiruv qidiruvni amalga oshirmaydi. Buning oârniga u dastlab natijalarsiz iteratsiya qilinadigan obyekt qaytaradi. Qidiruv har safar ustidan iteratsiya qilganimizda amalga oshiriladi, masalan tsiklda.
Shunday qilib, kerak boâlgandan koâp emas, balki kerak boâlganicha natijalar topiladi.
Masalan, matnda potensial 100 ta moslik bor, lekin for..of tsiklida ulardan 5 tasini topdik, keyin bu yetarli deb qaror qilib break qildik. Keyin dvigatel qolgan 95 ta moslikni topishga vaqt sarflamaydi.
Nomlangan guruhlar
Guruhlarni raqamlari boâyicha eslash qiyin. Oddiy naqshlar uchun bu mumkin, lekin murakkabroqlari uchun qavslarni sanash noqulay. Bizda ancha yaxshi variant bor: qavslarga nom berish.
Bu ochuvchi qavsdan keyin darhol ?<name> qoâyish orqali amalga oshiriladi.
Masalan, âyil-oy-kunâ formatida sanani qidiraylik:
let dateRegexp = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/;
let str = "2019-04-30";
let groups = str.match(dateRegexp).groups;
alert(groups.year); // 2019
alert(groups.month); // 04
alert(groups.day); // 30
Koârib turganingizdek, guruhlar moslikning .groups xususiyatida joylashgan.
Barcha sanalarni qidirish uchun g bayrogâini qoâshishimiz mumkin.
Shuningdek, guruhlar bilan birga toâliq mosliklarni olish uchun matchAll kerak boâladi:
let dateRegexp = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/g;
let str = "2019-10-30 2020-01-01";
let results = str.matchAll(dateRegexp);
for(let result of results) {
let {year, month, day} = result.groups;
alert(`${day}.${month}.${year}`);
// birinchi alert: 30.10.2019
// ikkinchi: 01.01.2020
}
Almashtirishda ushlash guruhlari
str dagi regexp bilan barcha mosliklarni replacement bilan almashtiradigan str.replace(regexp, replacement) metodi replacement satrida qavslar mazmunidan foydalanish imkonini beradi. Bu $n yordamida amalga oshiriladi, bu yerda n â guruh raqami.
Masalan,
let str = "John Bull";
let regexp = /(\w+) (\w+)/;
alert( str.replace(regexp, '$2, $1') ); // Bull, John
Nomlangan qavslar uchun havola $<name> boâladi.
Masalan, sanalarni "yil-oy-kun"dan "kun.oy.yil"ga qayta formatlaylik:
let regexp = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/g;
let str = "2019-10-30, 2020-01-01";
alert( str.replace(regexp, '$<day>.$<month>.$<year>') );
// 30.10.2019, 01.01.2020
?: bilan ushlamaydigan guruhlar
Baâzan miqdorchini toâgâri qoâllash uchun qavslar kerak, lekin natijalarda ularning mazmuni kerak emas.
Guruhni boshiga ?: qoâshish orqali chiqarib tashlash mumkin.
Masalan, agar biz (go)+ ni topmoqchi boâlsak, lekin qavslar mazmuni (go) ni massivning alohida elementi sifatida istamаÑak, yoza olamiz: (?:go)+.
Quyidagi misolda biz faqat John nomini moslikning alohida aâzosi sifatida olamiz:
let str = "Gogogo John!";
// ?: 'go' ni ushlashdan chiqarib tashlaydi
let regexp = /(?:go)+ (\w+)/i;
let result = str.match(regexp);
alert( result[0] ); // Gogogo John (to'liq moslik)
alert( result[1] ); // John
alert( result.length ); // 2 (massivda boshqa elementlar yo'q)
Xulosa
Qavslar doimiy ifodaning bir qismini birlashtirib guruhlaydi, shunda miqdorchi unga butunlay qoâllaniladi.
Qavslar guruhlari chapdan oângga raqamlanadi va ixtiyoriy ravishda (?<name>...) bilan nomlanishi mumkin.
Guruh tomonidan moslashtirilgan mazmunni natijalarda olish mumkin:
str.matchmetodi faqatgbayrogâisiz ushlash guruhlarini qaytaradi.str.matchAllmetodi har doim ushlash guruhlarini qaytaradi.
Agar qavslarning nomi boâlmasa, ularning mazmuni moslik massivida raqami boâyicha mavjud. Nomlangan qavslar groups xususiyatida ham mavjud.
Shuningdek, str.replace da almashtirish satrida qavslar mazmunidan foydalanishimiz mumkin: raqam $n yoki nom $<name> boâyicha.
Guruhni boshiga ?: qoâshish orqali raqamlashdan chiqarib tashlash mumkin. Bu butun guruhga miqdorchi qoâllashimiz kerak boâlganda, lekin uni natijalar massivida alohida element sifatida istamaganimizda ishlatiladi. Shuningdek, bunday qavslarni almashtirish satrida ham ishlatib boâlmaydi.
Izohlar
<code>yorlig'ini ishlating, bir nechta satrlar uchun - ularni<pre>yorlig'i bilan o'rab qo'ying, 10 satrdan ortiq bo'lsa - sandbox (plnkr, jsbin, codepenâ¦)