Mundarija (33)
- Bu darsda
- 1. Nega bu kerak?
- 2. Quantifier nima
- 2.1 Ta'rif
- 2.2 + — bir yoki ko'p (eslatma)
- 2.3 * — nol yoki ko'p
- 2.4 ? — ixtiyoriy
- 3. Aniq miqdor: {n}, {n,}, {n,m}
- 3.1 Jingalak qavslar
- 3.2 Telefon — qisqa va aniq
- 3.3 HTML formadagi namuna — endi to'liq
- 3.4 {,n} — JavaScript'da yo'q
- 4. Ochko'z quantifier (greedy)
- 4.1 "Imkon qadar ko'p"
- 4.2 Orqaga qaytish (backtracking)
- 5. Dangasa quantifier (lazy)
- 5.1 ? qo'shilsa
- 5.2 Dangasa — "eng qisqa" degani emas
- 5.3 Ko'pincha yaxshirog'i — inkor klass
- 6. Ko'p uchraydigan xatolar
- 6.1 .* bilan "hammasini" olib qo'yish
- 6.2 Quantifier butun so'zga tegishli deb o'ylash
- 6.3 * ni + o'rniga ishlatish
- 6.4 {,n} yozish
- 6.5 Langarsiz miqdor tekshiruvi
- 7. Mashqlar
- 1-mashq (oson): Pochta indeksi
- 2-mashq (o'rta): Bron vaqti
- 3-mashq (qiyin): Qavs ichidagi izohlar
- 4-mashq: Vazifalar qadami — teg kiritish maydoni
- 8. Real ishda
- Xulosa
- Manbalar
Regex quantifierlari: *, +, ?, {n,m} — greedy va lazy
Qisqacha: Quantifier o'zidan oldingi bitta bo'lak necha marta takrorlanishini aytadi:
*— 0 yoki ko'p,+— 1 yoki ko'p,?— 0 yoki 1,{3}— aynan 3,{2,}— 2 va undan ko'p,{1,2}— 1 dan 2 gacha. Standart holatda quantifier ochko'z (greedy): imkon qadar ko'p oladi, keyin kerak bo'lsa ortga qaytaradi. Oxiriga?qo'shilsa (+?,*?) — dangasa (lazy): imkon qadar kam oladi.
Bu darsda
*,+,?va{n},{n,},{n,m}bilan takrorlanishni qisqa yozasiz:\d{3}— "uch raqam".- HTML qismida yozgan telefon
patternini oxirigacha o'qiy olasiz. - Quantifier faqat oldingi bitta bo'lakka tegishli ekanini va bundan kelib chiqadigan xatolarni bilasiz.
- Ochko'z va dangasa quantifier farqini va orqaga qaytish (backtracking) qanday ishlashini qadamma-qadam ko'rasiz.
- Dangasa quantifier o'rniga ko'pincha inkor klass yaxshiroq ekanini tushuntira olasiz.
Oldin bilishingiz kerak: RegExp asoslari va metodlari, Belgilar va belgi klasslari, Langarlar va so'z chegarasi, Mobil klaviatura va kiritish yordamchilari.
1. Nega bu kerak?
O'tgan darsda telefonni shunday tekshirgan edik:
/^\+998 \d\d \d\d\d \d\d \d\d$/Ishlaydi, lekin \d\d\d ni sanab o'qish qiyin. Karta raqamida 16 ta raqam bo'lsa-chi — \d ni 16 marta yozamizmi? Va vaqt: 7:00 ham, 07:00 ham to'g'ri bo'lishi kerak — soat bir yoki ikki raqam. Bunday "yoki"ni hozircha yozolmaymiz.
Ikkinchi muammo. Sardor sharhlardan qo'shtirnoq ichidagi taom nomlarini ajratmoqchi:
const sharh = 'Menyu: "osh" va "manti" tayyor';
console.log(sharh.match(/".+"/)[0]); // "osh" va "manti"U "osh" ni kutgan edi. Regex esa birinchi qo'shtirnoqdan oxirgisigacha hammasini oldi. Nega?
Ikkala savolning javobi bitta mavzuda — quantifierlar. Birinchi darsda ulardan bittasi — + — bilan tanishgan edik. Bugun hammasini ko'ramiz va ularning "xarakteri" bilan tanishamiz.
2. Quantifier nima
2.1 Ta'rif
Quantifier (inglizcha "quantity" — miqdor so'zidan) — o'zidan oldingi bo'lak necha marta takrorlanishini belgilaydigan belgi. O'zbekcha "miqdor belgisi" deyish mumkin, lekin dasturchilar orasida inglizcha nomi ishlatiladi.
Oltita shakl bor:
| Quantifier | Necha marta | Misol | Mos keladi |
|---|---|---|---|
* |
0 yoki ko'p | \d* |
"", 5, 35000 |
+ |
1 yoki ko'p | \d+ |
5, 35000 |
? |
0 yoki 1 | \d? |
"", 5 |
{n} |
aynan n | \d{3} |
000 |
{n,} |
n yoki ko'p | \d{4,} |
5000, 35000 |
{n,m} |
n dan m gacha | \d{1,2} |
7, 23 |
Har biri bilan tanishamiz.
2.2 + — bir yoki ko'p (eslatma)
\d+ ni bilasiz: "bir yoki ko'p raqam". Endi bitta muhim narsaga e'tibor bering: quantifier faqat o'zidan oldingi bitta bo'lakka tegishli. /ha+/ — "h, keyin bir yoki ko'p a", "ha so'zi ko'p marta" emas:
const kulgi = "ha haaa haha";
console.log(kulgi.match(/ha+/g)); // [ 'ha', 'haaa', 'ha', 'ha' ]haaa — bitta moslik: a takrorlandi. haha esa ikkita alohida ha. Butun ha ni takrorlash uchun uni qavsga olish kerak — (ha)+. Qavslar Guruhlar va alternation darsida.
"Bitta bo'lak" — bitta belgi (a), escape (\d) yoki butun klass ([\w']). [\w']+ da + butun klassga tegishli.
2.3 * — nol yoki ko'p
* — "bo'lmasligi ham, ko'p marta bo'lishi ham mumkin". Bo'sh joy ixtiyoriy bo'lgan joylarda qulay. Menyu fayllarida Osh:35000, Osh : 35000, Osh :35000 — hammasi uchraydi:
" *" — "bo'sh joy, nol yoki ko'p marta". Bo'sh joy umuman bo'lmasa ham, uchta bo'lsa ham moslik bor. * o'rniga + qo'ysangiz, Osh:35000 tushib qoladi — u yerda bo'sh joy yo'q, + esa kamida bittasini talab qiladi.
* ning bir xavfi bor: u hech narsaga ham mos keladi. \d* naqshi raqami yo'q matnda ham "topadi" — bo'sh moslikni:
console.log("abc".match(/\d*/g)); // [ '', '', '', '' ]To'rtta bo'sh moslik: har harfdan oldin va oxirida. Bu xato emas — \d* haqiqatan "nol raqam"ga ruxsat beradi. Lekin natija foydasiz. Qoida: "kamida bitta" kerak bo'lsa — +, * emas.
2.4 ? — ixtiyoriy
? — "0 yoki 1 marta", ya'ni ixtiyoriy. Bo'lsa — bo'ladi, bo'lmasa — mayli.
O'tgan darsdagi bir xonali soat muammosi:
Soat — bitta majburiy raqam va bitta ixtiyoriy raqam. 7:00 ham, 23:00 ham mos keldi.
Yana bir foydali joy — o'zbekcha yozuvdagi farqlar. Ba'zilar so'm, ba'zilar som deb yozadi:
const narxlar = "35000 so'm, 5000 som";
console.log(narxlar.match(/so'?m/g)); // [ "so'm", 'som' ]'? — "apostrof bo'lishi ham, bo'lmasligi ham mumkin". Telefonda esa \+?998 — "plyus ixtiyoriy".
Tekshirib ko'ring:
/kishi?/naqshi"kish"ga mos keladimi? Qaysi harf ixtiyoriy?
Javob
Mos keladi. ? faqat oldingi bitta belgiga — i ga — tegishli. Naqsh "kish, keyin ixtiyoriy i" degani. Shuning uchun kish ham, kishi ham mos keladi. Butun so'zni ixtiyoriy qilish uchun guruh kerak.
3. Aniq miqdor: {n}, {n,}, {n,m}
3.1 Jingalak qavslar
*, +, ? — "nechta" degan savolga taxminiy javob. Aniq son kerak bo'lsa — jingalak qavslar:
\d{3}— aynan 3 ta raqam;\d{4,}— kamida 4 ta;\d{2,3}— 2 tadan 3 tagacha.
Uchala shaklning farqini bir matnda ko'ramiz:
const sonlar = "1 12 123 1234 12345";
console.log(sonlar.match(/\d{3}/g));
console.log(sonlar.match(/\d{3,}/g));
console.log(sonlar.match(/\d{2,3}/g));Konsolda:
[ '123', '123', '123' ]
[ '123', '1234', '12345' ]
[ '12', '123', '123', '123', '45' ]Birinchi natija g'alati ko'rinadi: nega uchta 123? \d{3} aynan uchta raqamni oladi. 1234 dan — birinchi uchtasini (123), 4 esa yolg'iz qoladi. 12345 dan ham — 123, qolgan 45 ikki raqam, uchinchisi yetmaydi. "Aynan uch xonali son" kerak bo'lsa, so'z chegarasi bilan o'rang: \b\d{3}\b.
Uchinchi natijada 12 dan 12 olindi, 1234 dan esa 123 — ikki raqam ham yetardi, lekin {2,3} imkon qadar ko'p, ya'ni uchta oldi. Qolgan 4 yolg'iz — ikki raqamga yetmaydi. Oxirgi son 12345 ikki bo'lakka bo'lindi: 123 va 45. "Imkon qadar ko'p" — bu quantifierlarning "ochko'zligi", u haqida birozdan keyin.
3.2 Telefon — qisqa va aniq
Endi o'tgan darsdagi telefon naqshini qisqartiramiz:
const telNaqshi = /^\+998 \d{2} \d{3} \d{2} \d{2}$/;
console.log(telNaqshi.test("+998 90 000 00 00")); // true
console.log(telNaqshi.test("+998 90 000 00 0")); // false\d{2} \d{3} \d{2} \d{2} — telefon raqamining shakli ko'z oldingizda: ikki, uch, ikki, ikki. Pochta indeksi — ^\d{6}$. PIN-kod va karta raqami ham xuddi shunday yoziladi, faqat jingalak qavs ichida boshqa son turadi.
O'zingiz to'ldiring: to'rt xonali PIN-kod naqshi — ^\d{4}$, bo'sh joysiz 16 xonali karta raqami uchun esa jingalak qavs ichiga yoziladi.
3.3 HTML formadagi namuna — endi to'liq
Mobil klaviatura va kiritish yordamchilari darsida HTML formaga shu namunani yozgan edik va "regex'ni keyin o'rganamiz" degan edik:
<input type="tel" pattern="\+998 ?\d{2} ?\d{3} ?\d{2} ?\d{2}">Endi uni o'zingiz o'qiy olasiz: plyus, 998, ixtiyoriy bo'sh joy, ikki raqam, ixtiyoriy bo'sh joy, uch raqam, ixtiyoriy bo'sh joy, ikki raqam, yana ixtiyoriy bo'sh joy va oxirgi ikki raqam. Maydonda sinang:
Uchinchi yozuvga e'tibor bering: +99890 0000000. Bo'sh joylar har xil joyda — lekin o'tdi. Har ? alohida ishlaydi va ular bir-biriga bog'liq emas. "Yo hamma bo'sh joy bor, yo hech biri" degan qoidani yozish uchun guruhlar kerak bo'ladi.
3.4 {,n} — JavaScript'da yo'q
Ba'zi tillarda {,3} — "ko'pi bilan 3". JavaScript'da bunday shakl yo'q. Eng yomoni — u xato ham bermaydi, oddiy matn sifatida qidiriladi:
console.log("aaa".match(/a{,3}/)); // null
console.log("a{,3}".match(/a{,3}/)[0]); // a{,3}/a{,3}/ aslida "a, keyin {, ,, 3, } belgilari" degan naqsh bo'lib qoldi. "Ko'pi bilan 3" — {0,3}.
u yoki v flagi bilan esa JavaScript qat'iyroq va to'g'ridan-to'g'ri xato beradi:
const naqsh = new RegExp("a{,3}", "u");SyntaxError: Invalid regular expression: /a{,3}/u: Incomplete quantifierTarjimasi: "Noto'g'ri muntazam ifoda: quantifier to'liq emas." u flagi haqida Unicode regex darsida batafsil gaplashamiz — qat'iy rejim tufayli u bunday jimgina xatolarni ushlaydi.
Tekshirib ko'ring:
^\d{1,2}:\d{2}$naqshi"7:00","07:00"va"123:00"dan qaysilarini qabul qiladi?
Javob
"7:00" va "07:00" ni. Soat — 1 yoki 2 raqam, daqiqa — aynan 2. "123:00" da soat uch raqamli. Langarlar bo'lmaganda esa 23:00 qismi topilib, test true berardi.
4. Ochko'z quantifier (greedy)
4.1 "Imkon qadar ko'p"
Endi «Nega bu kerak?» bo'limidagi ikkinchi savolga qaytamiz. ".+" nega butun "osh" va "manti" ni oldi?
Chunki standart holatda hamma quantifierlar ochko'z (greedy): ular imkon qadar ko'p belgi oladi. .+ — "istalgan belgi, imkon qadar ko'p". Matnda esa ikkinchi qo'shtirnoqdan keyin ham belgilar bor — va ular ham "istalgan belgi".
Bitta moslik — "osh" va "manti". Lekin regex qanday qilib aynan ikkinchi qo'shtirnoqda to'xtadi? .+ oxirigacha olgan bo'lsa, tayyor so'zi ham ichida bo'lishi kerak edi-ku?
4.2 Orqaga qaytish (backtracking)
Avval kim ishlayotganini aytaylik. Regex dvigateli (regex engine) — JS dvigateli ichidagi, naqshni matnga qo'llaydigan qism. Biz naqsh yozamiz, uni esa dvigatel belgima-belgi matn bilan solishtiradi.
Bu yerda dvigatelning asosiy mexanizmi ishga tushadi — orqaga qaytish (backtracking). Dvigatel naqshni chapdan o'ngga bajaradi. Bir qism ko'p olib qo'ysa va keyingi qism mos kelmasa, dvigatel oldingi qismdan bitta belgini qaytarib oladi va qaytadan urinadi.
Qadamlarni ko'ring. O'ngdagi bo'limda — dvigatel qayerda turgani va .+ nimani ushlab turgani:
Asosiy g'oyalar:
- Ochko'z quantifier avval hammasini oladi, keyin naqshning qolgani mos kelguncha bittalab qaytaradi. To'xtash joyi — o'ngdan birinchi mos keladigan joy. Shuning uchun moslik oxirgi qo'shtirnoqda tugadi.
- Orqaga qaytish — dvigatelning odatiy ishi, xato emas. Lekin har qaytarish — qo'shimcha ish. Bu misolda 8 ta. Uzun matnda va yomon yozilgan naqshda bu son juda katta bo'lishi mumkin — sahifa qotib qoladi. Bu xavf ReDoS deb ataladi, Regex amaliyotda va ReDoS darsida o'lchaymiz.
Tekshirib ko'ring:
"Narx: 35000 so'm".match(/\d{2,4}/)[0]nima qaytaradi?
Javob
"3500". {2,4} ochko'z — imkon qadar ko'p, ya'ni 4 ta raqam oladi. Beshinchi 0 ga ruxsat yo'q — chegara 4. Moslik birinchi raqamdan boshlanadi, shuning uchun 3500.
5. Dangasa quantifier (lazy)
5.1 ? qo'shilsa
Har quantifierdan keyin ? qo'ysangiz, u dangasa (lazy) bo'ladi: imkon qadar kam oladi va faqat naqshning qolgani mos kelmasa, bittadan qo'shib boradi.
| Ochko'z | Dangasa | Dangasa nimani afzal ko'radi |
|---|---|---|
* |
*? |
0 ta |
+ |
+? |
1 ta |
? |
?? |
0 ta |
{n,m} |
{n,m}? |
n ta |
Sardorning masalasi:
const sharh = 'Menyu: "osh" va "manti" tayyor';
console.log(sharh.match(/".+?"/g)); // [ '"osh"', '"manti"' ].+? birinchi uchragan qo'shtirnoqda to'xtadi. g bilan ikkinchi taom ham topildi.
Bu yerda ? belgisi ikki xil ma'noda kelganiga e'tibor bering. Oddiy bo'lak ortida (\d?) — "ixtiyoriy". Boshqa quantifier ortida (+?, *?) — "dangasa". Bitta belgi, ikki vazifa — kontekstga qarab.
5.2 Dangasa — "eng qisqa" degani emas
Dangasa quantifier "imkon qadar kam" oladi, lekin naqsh baribir mos kelishi kerak. Ikki misol:
console.log("Osh 35000 so'm".match(/\d+?/)[0]); // 3
console.log("Osh 35000 so'm".match(/\d+? so'm/)[0]); // 35000 so'mBirinchisida \d+? dan keyin hech narsa yo'q — bitta raqam yetarli, dangasa shu bilan to'xtadi. Ikkinchisida keyin so'm kerak. Dangasa avval 3 ni oldi, so'm mos kelmadi, 35 qildi, yana mos kelmadi... va 35000 gacha kengaydi.
Yana bir nozik joy. Dvigatel moslikni imkon qadar chapdan boshlaydi. Dangasalik faqat oxirini qisqartiradi, boshini emas:
console.log("<<osh>>".match(/<.*?>/)[0]); // <<osh>Eng qisqa moslik <osh> bo'lardi. Lekin dvigatel 0-o'rindagi < dan boshladi va u yerdan moslik topdi. Chaproqdagi boshlanish har doim ustun.
5.3 Ko'pincha yaxshirog'i — inkor klass
Qo'shtirnoq ichidagini olishning uchinchi yo'li ham bor — o'tgan darsdagi inkor klass:
const sharh = 'Menyu: "osh" va "manti" tayyor';
console.log(sharh.match(/"[^"]+"/g)); // [ '"osh"', '"manti"' ][^"]+ — "qo'shtirnoq bo'lmagan belgilar, imkon qadar ko'p". U ochko'z, lekin qo'shtirnoqdan o'ta olmaydi — klass unga ruxsat bermaydi. Natija dangasa variant bilan bir xil.
Nega bu yaxshiroq?
- Niyat aniq.
"[^"]+"o'qiladi: "qo'shtirnoq, qo'shtirnoqsiz belgilar, qo'shtirnoq". - Orqaga qaytish deyarli yo'q. Dangasa variant har belgidan keyin "endi qo'shtirnoqmi?" deb tekshiradi. Inkor klass esa bitta o'tishda kerakli joyda to'xtaydi.
- Kutilmagan holat kamroq. Masalan,
.yangi qatorni qabul qilmaydi,[^"]esa qabul qiladi. Qaysi biri kerakligini o'zingiz tanlaysiz.
Qoida: chegarachi belgi aniq bo'lsa (qo'shtirnoq, qavs, vergul) — inkor klass. Chegara murakkab bo'lsa (masalan, so'z) — dangasa quantifier.
Diqqat: Regex bilan HTML'ni "tahlil qilish"ga urinmang:
<b>.*?</b>oddiy holatda ishlaydi, lekin ichma-ich teglar, atributlardagi>belgisi va izohlar uni tezda buzadi. Brauzerda HTML uchun DOM bor (Elementlarni tanlash), serverda — maxsus kutubxonalar.
Tekshirib ko'ring:
"ali@example.com, vali@example.com".match(/.+@/)[0]nima qaytaradi? Dangasa variant/.+?@/-chi?
Javob
Ochko'z — "ali@example.com, vali@": .+ oxirigacha olib, ortga qaytib oxirgi @ ni topdi. Dangasa — "ali@": birinchi @ da to'xtadi. Inkor klass bilan esa: /[^@]+@/ — u ham "ali@".
O'zingiz to'ldiring: + quantifierining dangasa shakli deb yoziladi.
6. Ko'p uchraydigan xatolar
6.1 .* bilan "hammasini" olib qo'yish
".*", \(.*\), <.*> — chegarali bo'lakni olishga urinishda eng ko'p xato. Matnda bunday bo'lak ikkita bo'lsa, ochko'z quantifier birinchisining boshidan ikkinchisining oxirigacha oladi. Tuzatish: inkor klass ("[^"]*") yoki dangasa (".*?").
6.2 Quantifier butun so'zga tegishli deb o'ylash
/ha+/ — haaa, haha emas. /so'm?/ — "so', keyin ixtiyoriy m", "ixtiyoriy so'm" emas. Tuzatish: quantifier oldidagi bitta bo'lakka qarang. Ko'p belgili bo'lakni takrorlash — guruh bilan (Guruhlar).
6.3 * ni + o'rniga ishlatish
/\d*/ raqamsiz matnda ham bo'sh moslik beradi, test esa doim true. ^\d*$ bo'sh maydonni ham "to'g'ri" deydi. Tuzatish: kamida bitta kerak bo'lsa — + yoki {1,}.
6.4 {,n} yozish
JavaScript'da /a{,3}/ — quantifier emas, oddiy matn. Xato ham chiqmaydi. Tuzatish: {0,3}.
6.5 Langarsiz miqdor tekshiruvi
/\d{6}/.test("1234567") — true: yetti raqam ichida olti raqam bor. "Aynan olti raqam" — ^\d{6}$. Quantifier miqdorni faqat moslik ichida cheklaydi, atrofini emas.
7. Mashqlar
1-mashq (oson): Pochta indeksi
indeksTogrimi(qiymat) — qiymat aynan 6 ta raqamdan iborat bo'lsa true qaytarsin.
console.log(indeksTogrimi("100100")); // true
console.log(indeksTogrimi("10010")); // false
console.log(indeksTogrimi("1001001")); // falseYechim
function indeksTogrimi(qiymat) {
return /^\d{6}$/.test(qiymat.trim());
}
console.log(indeksTogrimi("100100")); // true
console.log(indeksTogrimi("10010")); // false
console.log(indeksTogrimi("1001001")); // false{6} miqdorni beradi, ^ va $ — atrofda boshqa narsa yo'qligini. Langarlarsiz uchinchi qiymat ham o'tardi.
2-mashq (o'rta): Bron vaqti
bronVaqtimi(qiymat) — 7:00 yoki 07:00 kabi vaqtni qabul qilsin: soat 1–2 raqam, daqiqa aynan 2 raqam. Keyin soatni songa aylantirib, «Bahor» bron vaqtini tekshiring: 10 dan 22 gacha (22:00 ham mumkin, 22:30 — yo'q).
console.log(bronVaqtimi("10:00")); // true
console.log(bronVaqtimi("9:30")); // false
console.log(bronVaqtimi("22:00")); // true
console.log(bronVaqtimi("22:30")); // falseYechim
function bronVaqtimi(qiymat) {
const vaqt = qiymat.trim();
if (!/^\d{1,2}:\d{2}$/.test(vaqt)) {
return false;
}
const [soat, daqiqa] = vaqt.split(":").map(Number);
if (daqiqa > 59) {
return false;
}
return soat >= 10 && (soat < 22 || (soat === 22 && daqiqa === 0));
}
console.log(bronVaqtimi("10:00")); // true
console.log(bronVaqtimi("9:30")); // false
console.log(bronVaqtimi("22:00")); // true
console.log(bronVaqtimi("22:30")); // falseRegex faqat shaklni tekshirdi. Ma'no — "10 dan 22 gacha" — oddiy JavaScript bilan, sonlar orqali. Bu yaxshi taqsimot: diapazonni regex bilan yozish mumkin, lekin o'qish qiyin bo'ladi va xato oson kiradi.
3-mashq (qiyin): Qavs ichidagi izohlar
Buyurtmalar ro'yxatida izohlar qavs ichida: "Osh (piyozsiz), manti (5 dona), choy". izohlarniOl(matn) qavs ichidagi matnlarni (qavslarsiz) massivda qaytarsin. Avval ochko'z \(.+\) bilan sinab ko'ring va nima bo'lishini tushuntiring. Ishora: qavslar metabelgi — \( va \); natijadagi qavslarni slice(1, -1) bilan olib tashlang.
console.log(izohlarniOl("Osh (piyozsiz), manti (5 dona), choy"));
// [ 'piyozsiz', '5 dona' ]Yechim
const buyurtma = "Osh (piyozsiz), manti (5 dona), choy";
console.log(buyurtma.match(/\(.+\)/g));
function izohlarniOl(matn) {
const topilgan = matn.match(/\([^)]*\)/g) ?? [];
return topilgan.map((izoh) => izoh.slice(1, -1));
}
console.log(izohlarniOl(buyurtma));Konsolda:
[ '(piyozsiz), manti (5 dona)' ]
[ 'piyozsiz', '5 dona' ]Ochko'z .+ birinchi ( dan oxirgi ) gacha oldi — bitta noto'g'ri moslik. [^)]* — "yopuvchi qavs bo'lmagan belgilar" — birinchi ) da to'xtaydi. * tanlandi, chunki () — bo'sh izoh ham bo'lishi mumkin. Qavslarsiz faqat ichini olishning toza yo'li — guruhlar, keyingi darsda.
4-mashq: Vazifalar qadami — teg kiritish maydoni
vazifalar ga kelajakda "Teg qo'shish" maydoni qo'shilsa, kiritilgan teg tekshirilishi kerak: # bilan boshlanadi, keyin 1 dan 20 tagacha so'z belgisi yoki apostrof. Shu tekshiruvni kurs/mashqlar/12/04-teglar/teg-tekshir.mjs da tegTogrimi(teg) funksiyasi sifatida yozing. Uni to'rt holatda sinang: #bozor, #do'kon, # va 21 harfli teg ("#" + "a".repeat(21)).
Yechim
function tegTogrimi(teg) {
return /^#[\w']{1,20}$/.test(teg);
}
const sinovlar = ["#bozor", "#do'kon", "#", "#" + "a".repeat(21)];
for (const teg of sinovlar) {
console.log(`${teg.slice(0, 8)} → ${tegTogrimi(teg)}`);
}Konsolda:
#bozor → true
#do'kon → true
# → false
#aaaaaaa → false{1,20} ikki tomondan cheklaydi: bo'sh teg (#) ham, juda uzuni ham o'tmaydi. ^ va $ bo'lmasa, 21 harfli teg ham o'tardi — ichida 20 harfli bo'lak bor. Uzun tegni konsolda kesib chiqardik (slice(0, 8)), qator cho'zilib ketmasin.
git add 12/04-teglar/teg-tekshir.mjs
git commit -m "12/04: teg uzunligini quantifier bilan tekshir"8. Real ishda
- Forma tekshiruvi. Telefon (
\d{2} \d{3} \d{2} \d{2}), pochta indeksi (\d{6}), SMS kodi (\d{4,6}), karta muddati (\d{2}\/\d{2}) — hammasi quantifier bilan. Zod kabi kutubxonalarda ham ichida xuddi shu regex'lar (kursda alohida o'rganamiz). - Matndan ajratib olish. Loglardan
"..."ichidagi xabarlar, CSV'dagi qo'shtirnoqli maydonlar — inkor klass bilan.".*"bilan yozilgan ajratuvchi production'da birinchi murakkab qatorda buziladi. - Tezlik va xavfsizlik. Ochko'z quantifier va orqaga qaytish — ReDoS hujumining ildizi. 2016-yilda Stack Overflow sayti bitta regex tufayli 34 daqiqa ishlamay qolgan (ularning rasmiy hisobotida bor). Buni ReDoS darsida ko'ramiz.
- Intervyu. "Greedy va lazy farqi?", "
.*?qachon kerak?", "{n,m}nima?" — junior va middle intervyularida ko'p so'raladi.
Xulosa
- Quantifier oldingi bitta bo'lakning takrorlanishini belgilaydi:
*(0+),+(1+),?(0–1),{n},{n,},{n,m}. {,n}JavaScript'da quantifier emas — jimgina oddiy matn bo'lib qoladi; to'g'risi{0,n}.- Ko'p belgili bo'lakni takrorlash uchun guruh kerak —
(ha)+(keyingi dars). - Standart quantifier ochko'z: avval hammasini oladi, keyin orqaga qaytib (backtracking) bittadan qaytaradi.
- Oxiriga
?qo'shilsa — dangasa (+?,*?): kam oladi, kerak bo'lsa kengayadi; moslik baribir eng chapdan boshlanadi. - Chegarachi belgi aniq bo'lsa, dangasa o'rniga inkor klass yaxshiroq:
"[^"]*".
Keyingi dars: Guruhlar, nomlangan guruhlar va alternation — qavslar bilan bo'laklarni guruhlaymiz, topilgan qismni alohida "ushlaymiz" va | bilan "yoki" yozamiz.
Manbalar
- MDN: "Quantifiers" (Regular expressions guide) — developer.mozilla.org
- ECMAScript 2025 Language Specification, 22.2.2.3.1 "RepeatMatcher" — tc39.es/ecma262
- Stack Exchange: "Outage Postmortem — July 20, 2016" — stackstatus.net
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!