IlmHamroh
JavaScript Full-stack/12-qism. JavaScript: ilg'or mavzular va kod sifati5/44-dars17 daqiqa
Mundarija (38)

Regex guruhlari: ( ), (?:), (?<nom>) va | alternation

Qisqacha: Qavslar ( ) naqshning bir qismini guruh qiladi: quantifier butun guruhga tegadi ((ha)+) va topilgan bo'lak alohida "ushlanadi" — moslik[1], moslik[2]. (?:...) faqat guruhlaydi, ushlamaydi. (?<yil>...) guruhga nom beradi — natija moslik.groups.yil da. Vertikal chiziq | — "yoki": osh|manti.

Bu darsda

  • Qavslar bilan naqsh bo'lagini guruhlaysiz va topilgan qismlarni [1], [2] orqali olasiz.
  • Nomlangan guruh (?<nom>...) bilan natijani groups.yil kabi o'qiladigan qilasiz.
  • | bilan "yoki" yozasiz va u nega ko'pincha qavs ichida turishini tushuntira olasiz.
  • \1 va \k<nom> bilan "oldin topilgan bo'lak yana takrorlansin" deysiz.
  • replace da $1 bilan topilgan bo'laklarni boshqa tartibda joylashtirasiz.

Oldin bilishingiz kerak: RegExp asoslari va metodlari, Langarlar va so'z chegarasi, Quantifierlar: greedy va lazy, Obyekt destructuring.

1. Nega bu kerak?

Sardor bron formasidan sanani oladi. Formada sana 2026-10-07 ko'rinishida keladi. Jasur aka esa uni 07.10.2026 ko'rinishida ko'rmoqchi. Buning uchun yil, oy va kunni alohida olish kerak.

Hozirgacha bilganlarimiz bilan sanani topish mumkin:

js
const bron = "Bron: 2026-10-07, soat 19:30";

console.log(bron.match(/\d{4}-\d{2}-\d{2}/)[0]); // 2026-10-07

Lekin natija — bitta yaxlit satr. Undan yilni olish uchun yana split("-") yoki slice kerak. Regex sanani qismlarga bo'lib "bilgan" edi-ku: avval to'rt raqam, keyin ikki, keyin yana ikki. Shu bilimni yo'qotmasdan olish mumkinmi?

O'tgan darslarda yana uchta savol ochiq qoldi:

  • (ha)+ — butun ha ni takrorlash (Quantifierlar darsida va'da qilingan);
  • soat 29:00 ni rad etish — "2 bilan boshlansa, keyin faqat 0–3" degan "yoki"li shart (Belgilar va belgi klasslari darsidan);
  • telefonda "yo hamma bo'sh joy bor, yo hech biri" degan qoida.

Uchalasining javobi — guruhlar. Bugun qavslarning to'rt xil ishini ko'ramiz.

2. Ushlovchi guruh: ( )

2.1 Qavslar bo'lakni ushlaydi

Guruh (group) — naqshning qavs ichiga olingan qismi. Oddiy qavs ( ) ikki ish qiladi. Birinchisi — ichidagini bitta bo'lakka aylantiradi. Ikkinchisi — shu bo'lakka mos kelgan matnni alohida eslab qoladi. Shuning uchun u ushlovchi guruh (capturing group) deb ataladi.

Sanadagi uch qismni qavsga olamiz:

js
const bron = "Bron: 2026-10-07, soat 19:30";
const moslik = bron.match(/(\d{4})-(\d{2})-(\d{2})/);

console.log(moslik[0]); // 2026-10-07
console.log(moslik[1]); // 2026
console.log(moslik[2]); // 10
console.log(moslik[3]); // 07

[0] — butun moslik, buni bilasiz. [1], [2], [3] — guruhlar, chapdan o'ngga tartib bilan. Naqsh o'zgarmadi: faqat qavslar qo'shildi. Mos keladigan matn ham o'sha. Farqi — regex endi bo'laklarni ham qaytaradi.

Butun natijani chiqarsak:

js
const bron = "Bron: 2026-10-07, soat 19:30";

console.log(bron.match(/(\d{4})-(\d{2})-(\d{2})/));

Konsolda:

text
[
  '2026-10-07',
  '2026',
  '10',
  '07',
  index: 6,
  input: 'Bron: 2026-10-07, soat 19:30',
  groups: undefined
]

Tanish massiv, faqat endi uzunroq. groups hali ham undefined — u nomlangan guruhlar uchun, ularga birozdan keyin yetamiz.

Maydonda sinang. Mosliklar jadvalida har moslik ostida guruhlar ham ko'rinadi — $1, $2, $3:

$1 — "birinchi guruh" degan yozuv. Uni replace da ham ishlatamiz.

2.2 Guruhlar qanday raqamlanadi

Guruh raqami — ochuvchi qavsning tartibi. Qavslar ichma-ich bo'lsa ham shu qoida:

js
const vaqt = "soat 19:30".match(/((\d{2}):(\d{2}))/);

console.log(vaqt[1]); // 19:30
console.log(vaqt[2]); // 19
console.log(vaqt[3]); // 30

Birinchi ochuvchi qavs — tashqi, u butun 19:30 ni o'rab turibdi. Ikkinchisi — soat, uchinchisi — daqiqa. Qavslarni chapdan sanang: ( uchragan tartib — guruh raqami.

2.3 Quantifier butun guruhga

O'tgan darsda /ha+/ faqat a ni takrorlagan edi. Qavs bilan endi butun ha takrorlanadi:

haaa dan faqat ha olindi: guruh ha ni takrorlaydi, a ni emas.

Bitta nozik joy bor. Guruh takrorlansa, u faqat oxirgi aylanishni eslab qoladi:

js
console.log("hahaha".match(/(ha)+/)[0]); // hahaha
console.log("hahaha".match(/(ha)+/)[1]); // ha

Butun moslik hahaha, [1] esa ha — uchinchi, oxirgi ha. Hamma takrorlarni alohida olish kerak bo'lsa — guruhni takrorlamang, g bilan matchAll ishlating.

Tekshirib ko'ring: "Soat 7:05".match(/(\d+):(\d+)/) natijasida [2] nima?

Javob

"05". Ikkinchi ochuvchi qavs — daqiqa guruhi. Natija satr: guruhlar har doim matn qaytaradi, son kerak bo'lsa Number("05") qiling.

3. Ushlamaydigan guruh: (?:...)

Ba'zan qavs faqat guruhlash uchun kerak: quantifier qo'yish yoki "yoki"ni chegaralash uchun. Topilgan bo'lak esa kerak emas. Shunda qavs ochilgandan keyin ?: yoziladi: (?:...) — ushlamaydigan guruh (non-capturing group).

js
console.log("hahaha".match(/(ha)+/));
console.log("hahaha".match(/(?:ha)+/));

Konsolda:

text
[ 'hahaha', 'ha', index: 0, input: 'hahaha', groups: undefined ]
[ 'hahaha', index: 0, input: 'hahaha', groups: undefined ]

Moslik bir xil. Ikkinchisida ortiqcha 'ha' yo'q.

Nega bu muhim? Ikki sabab bor:

  • Raqamlar siljimaydi. Naqshga yangi qavs qo'shsangiz, undan keyingi hamma guruh raqami bittaga suriladi. Kodda [2] ishlatgan joylar jimgina boshqa narsani ola boshlaydi. (?:...) raqamga ta'sir qilmaydi.
  • Niyat aniq. O'qigan odam biladi: bu qavs faqat guruhlash uchun.

O'tgan darslardagi ikki misolni endi o'qiy olasiz. "Ixtiyoriy so'm" — (?: so'm)?, butun so'z ixtiyoriy:

js
const narxlar = "35000 so'm, 5000";
const naqsh = /\d+(?: so'm)?/g;

console.log(narxlar.match(naqsh)); // [ "35000 so'm", '5000' ]

Langarlar darsida esa HTML pattern atributi naqshni ^(?:...)$ ga o'raydi, degan edik. Endi tushunarli: brauzer naqshingizni guruhlaydi, lekin hech narsani ushlamaydi.

4. Nomlangan guruh: (?<nom>...)

4.1 Raqam o'rniga nom

moslik[1], moslik[2] — qaysi biri yil, qaysi biri kun? Kodni o'qigan odam naqshga qaytib, qavslarni sanashi kerak. Nomlangan guruh (named group) buni hal qiladi: qavs ichida ?<nom> yoziladi.

js
const bron = "Bron: 2026-10-07, soat 19:30";
const naqsh = /(?<yil>\d{4})-(?<oy>\d{2})-(?<kun>\d{2})/;
const moslik = bron.match(naqsh);

console.log(moslik.groups.yil); // 2026
console.log(moslik.groups);

Konsolda:

text
2026
[Object: null prototype] { yil: '2026', oy: '10', kun: '07' }

groups endi obyekt: kalitlar — guruh nomlari, qiymatlar — topilgan matn. [Object: null prototype] — Node shuni aytyapti: bu obyektning prototipi yo'q, unda toString kabi meros metodlar ham yo'q. Brauzer konsoli shunchaki {yil: '2026', oy: '10', kun: '07'} deb ko'rsatadi — ma'nosi bir xil.

Nomlangan guruh raqamini ham saqlaydi: moslik[1] baribir 2026. Nom — qo'shimcha qulaylik.

4.2 Destructuring bilan

groups — oddiy obyekt kabi ishlaydi, shuning uchun Obyekt destructuring bilan qisqa yoziladi. Sardorning masalasi:

js
const bron = "Bron: 2026-10-07, soat 19:30";
const naqsh = /(?<yil>\d{4})-(?<oy>\d{2})-(?<kun>\d{2})/;
const { yil, oy, kun } = bron.match(naqsh).groups;

console.log(`${kun}.${oy}.${yil}`); // 07.10.2026

Uch qatorda sana ajratildi va qayta yig'ildi. Naqshni o'qigan odam ham, natijani ishlatgan odam ham bir xil nomlarni ko'radi.

Maslahat: Bir yoki ikki guruh bo'lsa, raqam ham tushunarli. Uch va undan ko'p guruh bo'lsa yoki naqsh kodning bir joyida, natija boshqa joyida ishlatilsa — nom bering. Kelajakdagi o'zingiz rahmat aytasiz.

Tekshirib ko'ring: /(?<soat>\d+):(?<daqiqa>\d+)/ naqshida moslik[2] va moslik.groups.daqiqa bir xil qiymatmi?

Javob

Ha. Nomlangan guruh ham raqamlanadi: soat — 1, daqiqa — 2. Ikkala yo'l bilan ham bir xil matn olinadi.

4.3 Qaysi qavsni tanlash

Endi uch xil qavsni bilasiz. Tanlash uchun ikki savol yetarli:

flowchart TD
  Q{"Topilgan bo'lak kerakmi?"} -->|"Yo'q, faqat guruhlash"| N["(?:...) — ushlamaydi"]
  Q -->|"Ha"| K{"Guruhlar ko'pmi?"}
  K -->|"1–2 ta"| R["( ) — natija [1], [2]"]
  K -->|"3 va undan ko'p"| M["(?#lt;nom#gt;...) — groups.nom"]

5. Alternation: | — "yoki"

5.1 Bir nechta variant

Alternation — vertikal chiziq | bilan yoziladigan "yoki". osh|manti — "osh yoki manti". Klass [...] bitta belgi uchun variant beradi, | esa butun bo'laklar uchun:

Variantlar soni cheklanmagan. Har biri to'liq naqsh bo'lishi mumkin: \d+ so'm|bepul.

5.2 | eng "kuchsiz" belgi

| naqshni butunlay ikkiga bo'ladi — chap tomonidagi hamma narsa bir variant, o'ng tomonidagi hammasi ikkinchi. Bu ko'p xatoga sabab bo'ladi. Sardor "faqat osh yoki faqat manti" deb tekshirmoqchi edi:

js
console.log(/^osh|manti$/.test("oshpaz")); // true
console.log(/^(?:osh|manti)$/.test("oshpaz")); // false

Birinchi naqsh aslida "^osh yoki manti$" — ya'ni "osh bilan boshlanadi yoki manti bilan tugaydi". oshpaz osh bilan boshlanadi — o'tib ketdi. Ikkinchisida | qavs ichida: langarlar ikkala variantga ham tegishli.

Qoida: | ni deyarli har doim qavs ichiga oling. Ushlash kerak bo'lmasa — (?:...).

5.3 Birinchi mos kelgan variant yutadi

Dvigatel variantlarni chapdan o'ngga sinaydi va birinchi mos kelganida to'xtaydi. Eng uzunini qidirmaydi:

js
console.log("oshxona".match(/osh|oshxona/)[0]); // osh
console.log("oshxona".match(/oshxona|osh/)[0]); // oshxona

Birinchi naqshda osh darhol mos keldi — oshxona hatto sinab ko'rilmadi. Qoida: bir variant ikkinchisining boshi bo'lsa, uzunini oldinga qo'ying. Yoki ikkalasini \b bilan o'rang.

5.4 Soat 00–23: va'da bajarildi

Belgilar va belgi klasslari darsida [0-2]\d:[0-5]\d naqshi 29:00 ni o'tkazib yuborgan edi. Soatning ikkinchi raqami birinchisiga bog'liq. Buni ikki variant bilan yozamiz:

  • birinchi raqam 0 yoki 1 bo'lsa — ikkinchisi istalgan: [01]\d;
  • birinchi raqam 2 bo'lsa — ikkinchisi faqat 0–3: 2[0-3].
js
const vaqt = /^(?:[01]\d|2[0-3]):[0-5]\d$/;

console.log(vaqt.test("07:00")); // true
console.log(vaqt.test("23:59")); // true
console.log(vaqt.test("29:00")); // false
console.log(vaqt.test("24:00")); // false

Qavs bu yerda shart: busiz | butun naqshni ^[01]\d va 2[0-3]:[0-5]\d$ ga bo'lib yuborardi.

Tekshirib ko'ring: /^choy|qahva$/ naqshi "choyxona" ga mos keladimi? Qanday tuzatasiz?

Javob

Mos keladi: naqsh "^choy yoki qahva$" deb o'qiladi, choyxona esa choy bilan boshlanadi. Tuzatish — /^(?:choy|qahva)$/: endi ikkala variant ham butun matnga teng bo'lishi shart.

O'zingiz to'ldiring: faqat guruhlaydigan, lekin hech narsani ushlamaydigan qavs belgilari bilan ochiladi.

6. Qayta havola: \1 va \k<nom>

6.1 "Xuddi o'sha bo'lak yana"

Guruh topgan matnni naqshning o'zida yana ishlatish mumkin. \1 — "birinchi guruh topgan aynan o'sha matn". Bu qayta havola (backreference) deb ataladi. Xuddi hujjatdagi "yuqoridagi bilan bir xil" degan belgi kabi: o'sha joyga yangi narsa emas, oldin yozilganning aynan o'zi qo'yiladi.

Sardor sharhlarda tasodifan ikki marta yozilgan so'zlarni qidiryapti:

js
const sharh = "Osh juda juda mazali, choy choy ham";

console.log(sharh.match(/\b(\w+) \1\b/g));
// [ 'juda juda', 'choy choy' ]

(\w+) — bir so'zni ushlaydi, keyin bo'sh joy, keyin \1 — o'sha so'z yana. \w+ \w+ ikkita har qanday so'zni topardi. \1 esa ikkinchisi birinchisiga teng bo'lishini talab qiladi.

Nomlangan guruhga nom bilan murojaat qilinadi — \k<nom>:

js
const sharh = "Osh juda juda mazali, choy choy ham";

const naqsh = /\b(?<soz>\w+) \k<soz>\b/g;

console.log(sharh.match(naqsh)); // [ 'juda juda', 'choy choy' ]

i flagi bilan qayta havola ham harf kattaligiga qaramaydi: /(\w+) \1/i naqshi Osh osh ni ham topadi.

6.2 Telefon: "hammasi bir xil"

Quantifierlar darsida telefon namunasi +99890 0000000 ni ham o'tkazib yuborgan edi: har ? alohida ishlaydi. Endi qoidani yozamiz: birinchi ajratuvchini ushlaymiz va qolganlari xuddi shunday bo'lsin.

( ?) — ixtiyoriy bo'sh joyni ushlaydi. Birinchi qatorda u bo'sh joyni ushladi — keyingi har \1 ham bo'sh joy bo'lishi shart. Ikkinchi qatorda u bo'sh matnni ushladi — keyingi \1 lar ham bo'sh. Uchinchi qator aralash, shuning uchun rad etildi. m flagi — Langarlar darsidan: ^ va $ har qatorda ishlaydi.

7. Guruhlar va metodlar

7.1 g bilan match guruhlarni yo'qotadi

RegExp asoslari darsidan eslang: g bilan match faqat matnlar massivini beradi. Guruhlar ham yo'qoladi. Har moslikning guruhlari kerak bo'lsa — matchAll:

js
const buyurtma = "Osh (piyozsiz), manti (5 dona), choy";
const naqsh = /\(([^)]*)\)/g;

console.log(buyurtma.match(naqsh));
console.log([...buyurtma.matchAll(naqsh)].map((m) => m[1]));

Konsolda:

text
[ '(piyozsiz)', '(5 dona)' ]
[ 'piyozsiz', '5 dona' ]

Quantifierlar darsidagi 3-mashqda qavslarni slice(1, -1) bilan kesgan edik. Endi qavslar guruhdan tashqarida, ichidagi matn esa guruhda. m[1] darhol kerakli bo'lakni beradi.

7.2 replace da $1

Almashtirish matnida $1, $2 — "shu guruh topgan matn". Bo'laklarni boshqa tartibda joylashtirish uchun eng qulay vosita:

js
const sana = "Bron: 2026-10-07";

console.log(sana.replace(/(\d{4})-(\d{2})-(\d{2})/, "$3.$2.$1"));
// Bron: 07.10.2026

Belgilar va belgi klasslari darsida telefonni slice bilan bo'laklagan edik va "guruhlar bilan bitta replace da qilish mumkin" degan edik. Mana u:

js
const raqamlar = "998900000000";
const naqsh = /^998(\d{2})(\d{3})(\d{2})(\d{2})$/;

console.log(raqamlar.replace(naqsh, "+998 $1 $2 $3 $4"));
// +998 90 000 00 00

Langarlar tufayli raqamlar soni noto'g'ri bo'lsa, naqsh mos kelmaydi va replace matnni o'zgartirmasdan qaytaradi.

O'zingiz to'ldiring: almashtirish matnida ikkinchi guruh topgan bo'lak deb yoziladi.

Ikki farqni eslab qoling: \1 — naqsh ichida, $1 — almashtirish matnida. $<nom> yozuvi, $& va almashtirish funksiyasiga guruhlar qanday kelishi — Almashtirish chuqur darsida.

7.3 split va guruh

Bitta kutilmagan xulq: split naqshida ushlovchi guruh bo'lsa, ajratuvchilar ham natijaga qo'shiladi:

js
console.log("10:00-22:00".split(/-/)); // [ '10:00', '22:00' ]
console.log("10:00-22:00".split(/(-)/)); // [ '10:00', '-', '22:00' ]

Ba'zan bu kerak — masalan, matnni bo'laklab, ajratuvchini ham saqlash uchun. Kerak bo'lmasa — (?:...).

8. Yangi imkoniyat: takrorlangan nomlar (ES2025)

Sana ikki ko'rinishda kelishi mumkin: 2026-10-07 yoki 07.10.2026. Ikkalasini bitta naqsh bilan o'qish uchun | kerak. Har variantda yil, oy, kun bor — va ularga bir xil nom bergimiz keladi.

Uzoq vaqt bunday qilib bo'lmas edi. ES2025 standartida ruxsat berildi: bir nom bir nechta guruhda takrorlanishi mumkin, agar ular | ning turli variantlarida bo'lsa.

js
const nuqtali = /(?<kun>\d{2})\.(?<oy>\d{2})\.(?<yil>\d{4})/;
const tireli = /(?<yil>\d{4})-(?<oy>\d{2})-(?<kun>\d{2})/;
const naqsh = new RegExp(`${nuqtali.source}|${tireli.source}`);

const birinchi = "07.10.2026".match(naqsh).groups;
const ikkinchi = "2026-10-07".match(naqsh).groups;

console.log(birinchi.yil, birinchi.oy, birinchi.kun); // 2026 10 07
console.log(ikkinchi.yil, ikkinchi.oy, ikkinchi.kun); // 2026 10 07

Naqsh uzun, shuning uchun uni ikki bo'lakda yozdik. Har bo'lakning source matnini (RegExp asoslari darsidan) | bilan qo'shib, bitta regex yasadik. Qaysi variant mos kelgan bo'lsa, groups.yil o'shandan olinadi. Bitta variant ichida bir nomni ikki marta yozish esa hali ham xato.

Bu imkoniyat Chrome 125, Firefox 129, Safari 17 va Node 23 dan beri bor (MDN ma'lumotlari, 2026-yil oktabr holati). Node 24 da ishlaydi. Eski brauzerlarni qo'llash kerak bo'lsa, nomlarni farqlang (yil1, yil2) — buni JS versiyalari va brauzer mosligi darsida chuqurroq ko'ramiz.

9. Ko'p uchraydigan xatolar

9.1 | ni qavssiz yozish

/^osh|manti$/ — "^osh yoki manti$". Langarlar va qo'shni bo'laklar faqat bitta variantga tegadi. Tuzatish: /^(?:osh|manti)$/.

9.2 Qisqa variantni oldinga qo'yish

/osh|oshxona/ hech qachon oshxona ni to'liq topmaydi. Tuzatish: uzunini oldinga yoki \b bilan o'rang: /\b(?:osh|oshxona)\b/.

9.3 Mos kelmagan guruh — undefined

| ning bir variantidagi guruh, boshqa variant mos kelsa, undefined bo'ladi:

js
const m = "soat 19:30".match(/(\d+):(\d+)|(\d+)\.(\d+)/);

console.log(m[3].padStart(2, "0"));
text
TypeError: Cannot read properties of undefined (reading 'padStart')

Tarjimasi: "undefined ning xususiyatlarini o'qib bo'lmaydi (padStart ni o'qishda)." Birinchi variant mos keldi, uchinchi guruh esa ikkinchi variantda edi — u hech narsa ushlamadi. Tuzatish: guruhni ishlatishdan oldin tekshiring (m[3] ?? m[1]) yoki takrorlangan nomli guruhlardan foydalaning.

9.4 Qavs qo'shib, raqamlarni siljitish

Naqshga (?:...) o'rniga oddiy (...) qo'shsangiz, undan keyingi guruhlarning raqami o'zgaradi. m[2] endi boshqa narsani oladi, xato esa chiqmaydi. Tuzatish: guruhlash uchun (?:...), ko'p guruhda — nomlar.

9.5 Mavjud bo'lmagan $2

js
console.log("ab".replace(/(a)/, "[$2]")); // [$2]b

Naqshda bitta guruh bor, $2 esa yo'q guruhga ishora qiladi. JavaScript xato bermaydi — $2 ni oddiy matn sifatida qo'yadi. Tuzatish: guruhlarni sanang yoki nomlardan foydalaning.

10. Mashqlar

1-mashq (oson): Vaqtni bo'laklash

vaqtniAjrat(matn) — "19:30" kabi matndan { soat, daqiqa } obyektini qaytarsin (qiymatlar son). Shakl noto'g'ri bo'lsa — null. Nomlangan guruhlar va Number ishlating.

js
console.log(vaqtniAjrat("19:30")); // { soat: 19, daqiqa: 30 }
console.log(vaqtniAjrat("7:05")); // { soat: 7, daqiqa: 5 }
console.log(vaqtniAjrat("19.30")); // null
Yechim
js
function vaqtniAjrat(matn) {
  const naqsh = /^(?<soat>\d{1,2}):(?<daqiqa>\d{2})$/;
  const moslik = matn.trim().match(naqsh);
  if (!moslik) {
    return null;
  }
  const { soat, daqiqa } = moslik.groups;
  return { soat: Number(soat), daqiqa: Number(daqiqa) };
}

console.log(vaqtniAjrat("19:30")); // { soat: 19, daqiqa: 30 }
console.log(vaqtniAjrat("7:05")); // { soat: 7, daqiqa: 5 }
console.log(vaqtniAjrat("19.30")); // null

match mos kelmasa null qaytaradi — shuning uchun avval tekshirdik. Guruhlar matn beradi: "05" ni Number 5 ga aylantirdi.

2-mashq (o'rta): Taom yoki ichimlik

Buyurtma qatorlari "2 osh", "1 ko'k choy" ko'rinishida keladi. buyurtmaniOqi(qator) — { soni, nom } qaytarsin, lekin faqat menyudagi nomlar uchun: osh, manti, lag'mon, ko'k choy. Boshqa nom bo'lsa — null. Ishora: nomlarni (?<nom>osh|manti|...) bilan yozing va butun qatorni ^...$ bilan o'rang.

js
console.log(buyurtmaniOqi("2 osh")); // { soni: 2, nom: 'osh' }
console.log(buyurtmaniOqi("1 ko'k choy"));
// { soni: 1, nom: "ko'k choy" }
console.log(buyurtmaniOqi("3 oshxona")); // null
Yechim
js
const naqsh =
  /^(?<soni>\d+) (?<nom>osh|manti|lag'mon|ko'k choy)$/;

function buyurtmaniOqi(qator) {
  const moslik = qator.trim().match(naqsh);
  if (!moslik) {
    return null;
  }
  return { soni: Number(moslik.groups.soni), nom: moslik.groups.nom };
}

console.log(buyurtmaniOqi("2 osh")); // { soni: 2, nom: 'osh' }
console.log(buyurtmaniOqi("1 ko'k choy"));
// { soni: 1, nom: "ko'k choy" }
console.log(buyurtmaniOqi("3 oshxona")); // null

Alternation guruh ichida — shuning uchun ^ va $ hamma variantga tegadi. oshxona rad etildi: osh dan keyin $ kerak edi, xona esa ortiqcha.

3-mashq (qiyin): Menyu matnidan obyektlar

Jasur aka menyuni har xil yozadi: ba'zan tire, ba'zan ikki nuqta, ba'zan so'm bilan, ba'zan usiz. menyuniOqi(matn) har qatordan { nom, narx } obyektini yasab, massiv qaytarsin. Ishora: m va g flaglari, matchAll, nomlangan guruhlar; ajratuvchi — (?: —|:), so'm — (?: so'm)?.

js
const menyu = `Osh — 35000 so'm
Lag'mon: 28000
Ko'k choy — 5000 so'm`;

console.log(menyuniOqi(menyu));
Yechim
js
const menyu = `Osh — 35000 so'm
Lag'mon: 28000
Ko'k choy — 5000 so'm`;

function menyuniOqi(matn) {
  const naqsh =
    /^(?<nom>[\w' ]+?)(?: —|:) (?<narx>\d+)(?: so'm)?$/gm;
  return [...matn.matchAll(naqsh)].map(({ groups }) => ({
    nom: groups.nom,
    narx: Number(groups.narx),
  }));
}

console.log(menyuniOqi(menyu));

Konsolda:

text
[
  { nom: 'Osh', narx: 35000 },
  { nom: "Lag'mon", narx: 28000 },
  { nom: "Ko'k choy", narx: 5000 }
]

[\w' ]+? — harf, apostrof yoki bo'sh joy, dangasa: ajratuvchidan oldingi bo'sh joyni nomga qo'shib yubormaslik uchun. Uchta ushlamaydigan guruh — ajratuvchi va ixtiyoriy so'm — natijaga hech narsa qo'shmadi. map callback'ida ({ groups }) — parametrda destructuring (Parametrda destructuring).

4-mashq: Vazifalar qadami — matndagi muddat

vazifalar foydalanuvchilari muddatni matnga yozib qo'yadi: "Hisobot topshirish 07.10.2026" yoki "Ijara to'lash 2026-10-15". Kelajakda "muddati o'tgan vazifalar" filtrini qo'shish uchun avval muddatni ajratishni o'rganamiz. kurs/mashqlar/12/05-muddat/muddat.mjs faylida muddatniOl(matn) yozing: ikki ko'rinishdan birini topib, "2026-10-07" shaklida qaytarsin, topilmasa null. Takrorlangan nomli guruhlardan foydalaning. vazifalar kodiga hozircha tegmang.

Yechim
js
const nuqtali = /(?<kun>\d{2})\.(?<oy>\d{2})\.(?<yil>\d{4})/;
const tireli = /(?<yil>\d{4})-(?<oy>\d{2})-(?<kun>\d{2})/;
const sanaNaqshi = new RegExp(`${nuqtali.source}|${tireli.source}`);

function muddatniOl(matn) {
  const moslik = matn.match(sanaNaqshi);
  if (!moslik) {
    return null;
  }
  const { yil, oy, kun } = moslik.groups;
  return `${yil}-${oy}-${kun}`;
}

const vazifalar = [
  "Hisobot topshirish 07.10.2026",
  "Ijara to'lash 2026-10-15",
  "Non olish",
];

for (const vazifa of vazifalar) {
  console.log(muddatniOl(vazifa));
}

Konsolda:

text
2026-10-07
2026-10-15
null

Bitta naqsh, ikki ko'rinish, uchta nom. Qaysi variant mos kelsa, groups o'sha variantdagi qiymatlarni oladi. "2026-10-07" shakli tasodifiy emas: bunday satrlarni oddiy < bilan solishtirsa ham sana tartibi to'g'ri chiqadi. Terminalda: node 12/05-muddat/muddat.mjs.

bash
git add 12/05-muddat/muddat.mjs
git commit -m "12/05: muddatni nomli guruhlar bilan ajrat"

11. Real ishda

  • Ma'lumot ajratish. Log qatorlari, CSV, SMS matnlari ("Kartangizdan 35000 so'm yechildi") — guruhlar bilan kerakli bo'laklar bitta qadamda olinadi. Bank va to'lov xabarlarini avtomatik o'qiydigan ilovalar shunday ishlaydi.
  • Marshrutlar. Sayt manzillaridagi /menyu/12 dan 12 ni olish — guruh. Express kabi server kutubxonalari (kursda keyin o'rganamiz) yo'llarni ichida regex guruhlariga aylantiradi. Brauzerdagi URLPattern ham shunday.
  • Kod vositalari. Stylelint va Prettier darsidagi /^(margin|padding|border)-(top|right|bottom|left)/ qoidasini endi to'liq o'qiy olasiz: ikki guruh, ikkalasida alternation. VS Code'ning "Almashtirish" maydonida ham $1 ishlaydi.
  • Intervyu. "Capturing va non-capturing guruh farqi?", "Backreference nima?", "Sanani DD.MM.YYYY ga aylantiring" — tez-tez beriladi.

Xulosa

  • ( ) — ushlovchi guruh: bo'lakni birlashtiradi va topilganini [1], [2] da beradi; raqam — ochuvchi qavs tartibi.
  • Quantifier guruhga tegadi ((ha)+), lekin guruh faqat oxirgi takrorni eslaydi.
  • (?:...) — faqat guruhlaydi, ushlamaydi: raqamlar siljimaydi, niyat aniq.
  • (?<nom>...) — natija groups.nom da; destructuring bilan qulay; ES2025 dan bir nom | ning turli variantlarida takrorlanishi mumkin.
  • | — "yoki", eng kuchsiz belgi: deyarli har doim qavs ichida; birinchi mos kelgan variant yutadi.
  • \1 va \k<nom> — naqsh ichida "o'sha bo'lak yana"; $1 — almashtirish matnida.

Keyingi dars: Flaglar va lastIndex tuzog'i — sakkizta flagning hammasini ko'ramiz va g bilan test nega true, false deb "sakrashini" ochamiz.

Manbalar

  • MDN: "Groups and backreferences", "Named capturing group", "Disjunction" — developer.mozilla.org
  • ECMAScript 2025 Language Specification, 22.2.1 "Patterns" (Atom, GroupSpecifier, Disjunction) — tc39.es/ecma262
  • TC39 taklifi: "Duplicate named capturing groups" — github.com/tc39/proposal-duplicate-named-groups
  • MDN browser-compat-data 8.1.4 — takrorlangan nomli guruhlar qo'llanishi
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Regex guruhlari: ( ), (?:), (?<nom>) va | alternation — IlmHamroh