Mundarija (35)
- Bu darsda
- 1. Nega bu kerak?
- 2. Almashtirish matnidagi maxsus belgilar
- 2.1 Eslatma: $&
- 2.2 $1, $2 — guruh raqami bilan
- 2.3 $<nom> — nomlangan guruh
- 2.4 Barcha almashtirish belgilari
- 2.5 Mavjud bo'lmagan guruh
- 3. Funksiya bilan almashtirish
- 3.1 Qachon matn yetmaydi
- 3.2 Callback'ga nima keladi
- 3.3 Kerak bo'lmagan argument: _
- 3.4 Funksiya natijasi so'zma-so'z qo'yiladi
- 4. replace va replaceAll
- 5. Dinamik regex: foydalanuvchi matnidan naqsh
- 5.1 Muammo
- 5.2 RegExp.escape
- 5.3 Qayerda ishlaydi
- 5.4 Escape — faqat tashqaridan kelgan bo'lakka
- 5.5 Qo'yiladigan tomonni ham himoya qilish
- 6. Hujumchi nigohi
- 7. Ko'p uchraydigan xatolar
- 7.1 Naqshga qavs qo'shib, $1 ni unutish
- 7.2 Shablon satrda $ bilan adashish
- 7.3 Callback'da return yo'q
- 7.4 Butun naqshni escape qilish
- 7.5 Escape'ni unutish
- 8. Mashqlar
- 1-mashq (oson): Sana formati
- 2-mashq (o'rta): Telefon — bitta replace bilan
- 3-mashq (qiyin): Qidiruv natijasini belgilash
- 4-mashq: Vazifalar qadami — vazifa matnini tozalash
- 9. Real ishda
- Xulosa
- Manbalar
Regex bilan almashtirish: $1, $<nom>, funksiya va xavfsiz RegExp.escape
Qisqacha:
replacening ikkinchi argumentida maxsus belgilar ishlaydi:$&— butun moslik,$1,$2— raqamli guruhlar,$<nom>— nomlangan guruh,$$— dollarning o'zi. Hisob kerak bo'lsa, ikkinchi argument funksiya bo'ladi: u har moslik uchun chaqiriladi va qaytargani so'zma-so'z qo'yiladi. Foydalanuvchi matnidan regex yasashda uni avvalRegExp.escape(matn)bilan ekranlang — aks holda.va(kabi belgilar buyruqqa aylanadi.
Bu darsda
- Almashtirish matnidagi
$&,$1,$<nom>,$`,$'va$$ning har birini ishlatasiz. - Funksiya bilan almashtirasiz va callback'ga keladigan argumentlarni bilasiz.
replacevareplaceAllsatr va regex bilan qanday farq qilishini aytib bera olasiz.- Foydalanuvchi so'zidan
RegExp.escapebilan xavfsiz regex yasaysiz va eski brauzerlar uchun zaxira yo'lni bilasiz. - Almashtirish matnining o'zida yashiringan
$tuzog'ini funksiya bilan yopasiz.
Oldin bilishingiz kerak: RegExp asoslari va metodlari, Guruhlar, nomlangan guruhlar va alternation, Unicode regex: u va v flag, Funksiya — qiymat: callback va HOF.
1. Nega bu kerak?
«Bahor» saytiga ikki yangi ish tushdi.
Birinchisi — sanalar. Bron tizimi sanani 2026-10-05 ko'rinishida saqlaydi. Mehmonga esa 05.10.2026 ko'rsatish kerak. Sardor split("-") qilib, bo'laklarni teskari yig'ishi mumkin. Lekin sana uzun matn ichida turibdi: "Bron: 2026-10-05, soat 19:00". Unga "topilgan bo'lakni qayta tartiblab qo'y" degan vosita kerak.
Ikkinchisi — qidiruv. Menyu sahifasiga qidiruv maydoni qo'shildi. Sardor foydalanuvchi so'zidan regex yasadi: new RegExp(soz, "gi"). Birinchi kun hammasi yaxshi edi. Keyin bir mehmon 1.5 deb yozdi — sayt 125 ni ham topdi. Boshqasi (osh deb yozdi — sahifa xato bilan yiqildi.
Ikkala masala ham shu darsda hal bo'ladi. RegExp asoslari darsida replace va $& bilan tanishgan edik va "hamma imkoniyatlari keyin" degan edik. O'sha "keyin" keldi.
2. Almashtirish matnidagi maxsus belgilar
2.1 Eslatma: $&
replace(naqsh, yangi) da yangi oddiy matnga o'xshaydi. Lekin unda dollar $ bilan boshlanadigan bir nechta almashtirish belgisi (replacement pattern) ishlaydi. Ulardan birini bilasiz — $&, "butun moslik":
console.log("Osh 35000".replace(/\d+/, "[$&]")); // Osh [35000]Almashtirish belgisini pochtadagi blankaga o'xshatish mumkin. Blankada "Qabul qiluvchi: ____" degan bo'sh joy bor — xodim unga ismni yozadi. $& ham shunday bo'sh joy: replace uning o'rniga topilgan bo'lakni yozadi.
2.2 $1, $2 — guruh raqami bilan
Guruhlar darsida qavslar topilgan bo'lakni "ushlashini" ko'rgan edingiz. Ushlangan bo'lakni almashtirish matnida raqami bilan chaqirasiz: birinchi qavs — $1, ikkinchisi — $2. Raqam — chapdan sanaganda nechanchi ochiluvchi qavs ekani.
Sardorning sana masalasi:
const bron = "Bron: 2026-10-05, soat 19:00";
console.log(bron.replace(/(\d{4})-(\d{2})-(\d{2})/, "$3.$2.$1"));
// Bron: 05.10.2026, soat 19:00Naqsh sanani uch guruhga bo'ldi: yil ($1), oy ($2), kun ($3). Almashtirish matni ularni teskari tartibda, nuqta bilan yig'di. Matnning qolgan qismi tegilmay qoldi.
Guruhlar nimani ushlaganini maydonda ko'ring. Mosliklar jadvalida har guruhning qiymati alohida ustunda turadi:
Izohdagi tajribani albatta qiling. Ushlamaydigan guruh (?:...) raqam olmaydi. Shuning uchun naqshga qavs qo'shsangiz yoki olib tashlasangiz, $1, $2 ning ma'nosi jimgina o'zgaradi. Bu raqamli guruhlarning eng katta zaif joyi.
2.3 $<nom> — nomlangan guruh
Nomlangan guruh (?<nom>...) bu muammoni hal qiladi. Almashtirish matnida uni $<nom> bilan chaqirasiz:
const bron = "Bron: 2026-10-05, soat 19:00";
const sana = /(?<yil>\d{4})-(?<oy>\d{2})-(?<kun>\d{2})/;
console.log(bron.replace(sana, "$<kun>.$<oy>.$<yil>"));
// Bron: 05.10.2026, soat 19:00Natija bir xil, lekin almashtirish matni o'qiladi: "kun, oy, yil". Naqshga yangi guruh qo'shilsa ham, $<kun> baribir kunni bildiradi.
Maydonda nomlar jadvalda qanday ko'rinishiga qarang:
Qoida: ikki-uchtadan ko'p guruh bo'lsa yoki kodni boshqalar ham o'qisa — nomlangan guruh. Bitta qisqa guruh uchun $1 ham yetadi.
2.4 Barcha almashtirish belgilari
To'liq ro'yxat oltita:
| Belgi | Nima qo'yiladi |
|---|---|
$& |
butun moslik |
$1 … $99 |
shu raqamli guruh |
$<nom> |
shu nomli guruh |
$` |
moslikdan oldingi butun matn |
$' |
moslikdan keyingi butun matn |
$$ |
bitta $ belgisi |
Oxirgi uchtasi kam ishlatiladi, lekin bir marta ko'rib qo'ying:
const matn = "Osh 35000 so'm";
console.log(matn.replace(/\d+/, "[$`|$'|$&]"));
// Osh [Osh | so'm|35000] so'm$` — moslikdan oldingi "Osh ", $' — undan keyingi " so'm". Ular ham moslik o'rniga qo'yildi, shuning uchun matn g'alati "ikkilandi".
$$ esa dollarning o'zi kerak bo'lganda yoziladi. Almashtirish matnida yolg'iz $ ko'pincha o'zini bildiradi, lekin keyingi belgi &, raqam, <, backtick yoki apostrof bo'lsa — buyruqqa aylanadi. Ishonchli bo'lish uchun $$ yozing.
2.5 Mavjud bo'lmagan guruh
Guruh yo'q bo'lsa, almashtirish belgisi oddiy matn bo'lib qoladi:
console.log("a".replace(/(a)/, "$2")); // $2
console.log("a".replace(/(a)/, "$10")); // a0
console.log("a".replace(/a/, "$0")); // $0Ikkinchi qator qiziq. Naqshda bitta guruh bor, $10 esa "o'ninchi guruh". Bunday guruh yo'q, shuning uchun JavaScript uni $1 va 0 deb o'qidi. $0 esa umuman belgi emas — butun moslik uchun $& bor.
Nomlangan guruhlarda tartib boshqacha. Naqshda birorta ham nomli guruh bo'lmasa, $<nom> so'zma-so'z qoladi. Nomli guruhlar bor-u, aynan shu nom yo'q bo'lsa — bo'sh satr qo'yiladi:
console.log("x".replace(/x/, "$<nom>")); // $<nom>
console.log("x".replace(/(?<a>x)/, "[$<nom>]")); // []Bu jim xato: nomni noto'g'ri yozsangiz, xabar chiqmaydi, natijada shunchaki bo'sh joy qoladi. Shuning uchun almashtirishdan keyin natijani bir marta konsolda ko'ring.
Tekshirib ko'ring:
"07:00".replace(/(\d{2}):(\d{2})/, "$2:$1")nima qaytaradi?"$2$1"bo'lsa-chi?
Javob
Birinchisi — "00:07": daqiqa va soat joyini almashtirdi. Ikkinchisi — "0007": ikki guruh orasida ikki nuqta yo'q. Almashtirish matnidagi oddiy belgilar (:) o'zi qanday bo'lsa, shunday qo'yiladi.
3. Funksiya bilan almashtirish
3.1 Qachon matn yetmaydi
Almashtirish matni bo'laklarni faqat joyidan siljita oladi. Ular ustida hisob qila olmaydi: narxni ikki baravar qilish, harfni katta qilish, ro'yxatdan qidirish. Buning uchun ikkinchi argument funksiya bo'ladi. RegExp asoslari darsida narxlarni shunday ikki baravar qilgan edik.
Funksiya har moslik uchun alohida chaqiriladi. U nima qaytarsa, shu moslik o'rniga qo'yiladi.
3.2 Callback'ga nima keladi
Callback bir nechta argument oladi. Ularni ko'rish uchun hammasini massivga yig'ib, konsolga chiqaramiz. (...arg) — rest parametr: "nechta argument kelsa, hammasini massivga yig'".
const menyu = "Osh 35000, choy 5000";
const naqsh = /(?<nom>\p{L}+) (?<narx>\d+)/gu;
menyu.replace(naqsh, (...arg) => {
console.log(arg);
return "";
});Konsolda:
[
'Osh 35000',
'Osh',
'35000',
0,
'Osh 35000, choy 5000',
[Object: null prototype] { nom: 'Osh', narx: '35000' }
]
[
'choy 5000',
'choy',
'5000',
11,
'Osh 35000, choy 5000',
[Object: null prototype] { nom: 'choy', narx: '5000' }
]Har chaqiruvda argumentlar shu tartibda keladi:
- butun moslik (
$&bilan bir xil); - guruhlar — har biri alohida argument (
$1,$2, ...); guruh nechta bo'lsa, shuncha; - moslik boshlangan indeks (
0, keyin11); - butun asl matn;
- nomlangan guruhlar obyekti — faqat naqshda nomli guruh bo'lsa.
[Object: null prototype] — bu obyektning prototipi yo'qligini bildiradi (Prototip zanjiri darsidan). Unga nom va narx ni oddiy obyektdagidek o'qiysiz. \p{L} — o'tgan darsdan: "istalgan tildagi harf".
Guruhlar soni naqshga qarab o'zgargani uchun indeks va matn argumentlarining o'rni ham suriladi. Shuning uchun ko'pincha faqat kerakli birinchi argumentlar nomlanadi.
3.3 Kerak bo'lmagan argument: _
Ism-familiyani chiroyli qilamiz: har so'zning birinchi harfi katta bo'lsin. Bron formasiga mehmonlar ismni har xil yozadi:
const ism = "g'ayrat aka";
const yangi = ism.replace(
/(^|\s)(\p{Ll})/gu,
(_, oldi, harf) => oldi + harf.toUpperCase(),
);
console.log(yangi); // G'ayrat AkaNaqsh: matn boshi yoki bo'sh joy ($1), keyin kichik harf ($2). \p{Ll} — "kichik harf (lowercase letter)", o'tgan darsdagi Unicode xususiyati. \w va \b bu yerda ishlamasdi: g'ayrat dagi apostrofdan keyingi a ni ham "so'z boshi" deb olardi.
Birinchi argument — butun moslik — bizga kerak emas, lekin u baribir birinchi keladi. Dasturchilar bunday parametrni _ (pastki chiziq) deb nomlaydi: "bu yerda argument bor, lekin men uni ishlatmayman".
3.4 Funksiya natijasi so'zma-so'z qo'yiladi
Funksiya qaytargan matndagi $ belgilari ishlamaydi. Bu kichik detal, lekin xavfsizlik uchun muhim — keyingi bo'limlarda kerak bo'ladi:
const shablon = "Izoh: {matn}";
const izoh = "Chegirma $& bonus";
console.log(shablon.replace("{matn}", izoh));
console.log(shablon.replace("{matn}", () => izoh));Konsolda:
Izoh: Chegirma {matn} bonus
Izoh: Chegirma $& bonusBirinchi qatorda izoh ichidagi $& "butun moslik" deb tushunildi va {matn} ga aylandi. Ikkinchisida funksiya qaytargan matn o'zgarishsiz qo'yildi.
Yana bir narsa: funksiya return qilishni unutsa, moslik o'rniga "undefined" matni qo'yiladi:
console.log("osh".replace(/osh/, () => {})); // undefinedTekshirib ko'ring:
"Osh 35000".replace(/\d+/, (narx) => narx / 1000 + " ming")nima qaytaradi?
Javob
"Osh 35 ming". Callback'ga "35000" satri keldi. Bo'lish / satrni o'zi songa aylantirdi: 35. Keyin " ming" qo'shildi va natija moslik o'rniga qo'yildi.
4. replace va replaceAll
Birinchi argument satr ham, regex ham bo'lishi mumkin. Ikkala metodning to'rt holati bitta jadvalda:
| Chaqiruv | Nechta almashadi |
|---|---|
replace("osh", ...) |
faqat birinchisi |
replaceAll("osh", ...) |
hammasi |
replace(/osh/g, ...) |
hammasi (g siz — birinchisi) |
replaceAll(/osh/g, ...) |
hammasi; g siz — TypeError |
Satr bilan replaceAll — eng sodda yo'l. U satrni so'zma-so'z qidiradi, nuqta ham oddiy nuqta:
console.log("osh, osh".replaceAll("osh", "manti")); // manti, manti
console.log("a.b.c".replaceAll(".", "-")); // a-b-creplaceAll ga g siz regex bersangiz, JavaScript to'xtatadi:
"osh".replaceAll(/osh/, "manti");TypeError: String.prototype.replaceAll called with a non-global RegExp argumentTarjimasi: "replaceAll global bo'lmagan regex bilan chaqirildi." matchAll dagi xato bilan bir xil sabab: "hammasini almashtir" deb, "faqat birinchisini top" degan regex berish deyarli har doim adashish.
E'tibor bering: satr bilan chaqirganda ham almashtirish belgilari ishlaydi. Yuqoridagi {matn} misolida birinchi argument satr edi, lekin $& baribir buyruq bo'ldi. Qidiriladigan tomon so'zma-so'z, qo'yiladigan tomon esa yo'q.
Qaysi birini tanlash kerak? Aniq matn almashsa — replaceAll("eski", "yangi"). Shakl bo'yicha almashsa — replace(/.../g, ...). Regex bilan replace(/.../g) va replaceAll(/.../g) bir xil ishlaydi.
O'zingiz to'ldiring: replaceAll ga regex bersangiz, unda flagi bo'lishi shart.
5. Dinamik regex: foydalanuvchi matnidan naqsh
5.1 Muammo
Endi «Nega bu kerak?» bo'limidagi ikkinchi masalaga qaytamiz. Naqsh kod yozilganda ma'lum emas — uni foydalanuvchi kiritadi. Bunday regex dinamik regex deb ataladi. U faqat new RegExp bilan yasaladi.
Mehmon 1.5 deb qidirdi:
const matn = "1.5 kg guruch, 125 g sariyog'";
console.log(matn.match(new RegExp("1.5", "g"))); // [ '1.5', '125' ]Nuqta regex'da "istalgan belgi". Shuning uchun 125 ham mos keldi. Boshqa mehmon (osh deb yozdi:
const naqsh = new RegExp("(osh", "gi");SyntaxError: Invalid regular expression: /(osh/gi: Unterminated groupTarjimasi: "Noto'g'ri muntazam ifoda: guruh yopilmagan." Ochiluvchi qavs guruh boshi deb tushunildi, yopuvchisi esa yo'q. try/catch bo'lmasa, qidiruv funksiyasi to'xtaydi.
Ikkala holatda sabab bitta: foydalanuvchi oddiy matn yozdi, biz esa uni naqsh deb o'qidik. Yechim — matndagi hamma metabelgilarni escape qilish. Shunda . oddiy nuqta, ( oddiy qavs bo'ladi.
5.2 RegExp.escape
ES2025 standartida buning uchun tayyor funksiya bor — RegExp.escape(matn). U matnni oladi va undan "aynan shu matnni qidiradigan" naqsh satrini qaytaradi:
const soz = "1.5";
const naqsh = new RegExp(RegExp.escape(soz), "g");
const matn = "1.5 kg guruch, 125 g sariyog'";
console.log(naqsh.source); // \x31\.5
console.log(matn.match(naqsh)); // [ '1.5' ]Nuqta \. bo'ldi — endi faqat nuqtaning o'zi. 125 topilmadi.
Lekin birinchi belgi 1 g'alati ko'rinishga keldi: \x31. Bu belgining o'n oltilik (hex) kodi bilan yozilishi — \x31 aynan 1 raqamini bildiradi. Nega? Escape qilingan bo'lak ko'pincha boshqa naqsh bo'lagiga ulanadi. Undan oldin \1 yoki \c kabi narsa tursa, 1 yoki harf ular bilan "yopishib", ma'noni buzishi mumkin edi. Shuning uchun RegExp.escape boshidagi raqam yoki harfni har doim kod bilan yozadi.
Ko'proq misol:
console.log(RegExp.escape("+998 (90)"));
console.log(RegExp.escape("so'm"));
console.log(RegExp.escape("osh-manti"));Konsolda:
\+998\x20\(90\)
\x73o\x27m
\x6fsh\x2dmantiMetabelgilar (+, (, )) oldiga \ qo'yildi. Bo'sh joy, apostrof va chiziqcha esa kod bilan yozildi (\x20, \x27, \x2d). Ular hozircha maxsus emas. Lekin v flagli klassda yoki kelajakdagi sintaksisda maxsus bo'lishi mumkin — RegExp.escape oldindan himoya qiladi.
Natijani ko'z bilan o'qish shart emas. Uning vazifasi bitta: hosil bo'lgan naqsh aynan berilgan matnni topsin. Maydonda o'zingiz ko'ring:
5.3 Qayerda ishlaydi
RegExp.escape — yangi funksiya. Baseline ma'lumotiga ko'ra u 2025-yil may oyidan Baseline (barcha asosiy brauzerlarda bor): Chrome va Edge 136, Firefox 134, Safari 18.2 dan boshlab. Biz Chrome 154 va Node 24 da sinab ko'rdik — ikkalasida ham ishlaydi. Baseline nima ekanini Veb standartlari va brauzer mosligi darsida ko'rgansiz.
Eski brauzerni ham qo'llash kerak bo'lsa, ko'p yillardan beri ishlatilgan qo'lda yozilgan variant bor:
function regexniEkranla(matn) {
return matn.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
console.log(regexniEkranla("+998 (90) 1.5")); // \+998 \(90\) 1\.5Klassda barcha metabelgilar sanab chiqilgan. "\\$&" — "teskari chiziq va butun moslik": har metabelgi oldiga \ qo'yiladi. Bu variant u/v flagsiz oddiy naqsh uchun yetarli. RegExp.escape bor joyda — o'shani ishlating: uni standart yozganlar hamma chekka holatni o'ylab chiqqan.
5.4 Escape — faqat tashqaridan kelgan bo'lakka
Escape butun naqshga emas, faqat foydalanuvchi bergan bo'lakka qo'llanadi. Atrofidagi o'z bo'laklaringiz esa ishlashi kerak. Masalan, qidiruv so'z ichidagi bo'lakni emas, alohida so'zni topsin:
function qidiruvNaqshi(soz) {
const toza = RegExp.escape(soz);
return new RegExp(`(?<!\\p{L})${toza}(?!\\p{L})`, "giu");
}
const menyu = "Osh, oshqovoq somsa, qovoq osh";
console.log(menyu.match(qidiruvNaqshi("osh"))); // [ 'Osh', 'osh' ](?<!\p{L}) va (?!\p{L}) — bizning bo'laklar: "oldida ham, ortida ham harf bo'lmasin" (Lookahead va lookbehind darsidan). Shuning uchun oshqovoq ichidagi osh tashlab ketildi. O'rtadagi bo'lak esa foydalanuvchiniki va u escape qilingan.
Ikki detal. Birinchisi — shablon satrda \\p{L} ikki teskari chiziq bilan yozildi: satr bittasini yutadi (RegExp asoslari darsidagi tuzoq). Ikkinchisi — u flagi. \p{L} faqat u bilan ishlaydi. RegExp.escape natijasi esa u va v bilan ham, ularsiz ham to'g'ri ishlaydi.
5.5 Qo'yiladigan tomonni ham himoya qilish
Qidiriladigan tomonni RegExp.escape himoya qildi. Lekin foydalanuvchi matni almashtirish matni sifatida ham kelishi mumkin. Unda $& yoki $` bo'lsa, ular buyruqqa aylanadi — buni funksiya natijasi so'zma-so'z qo'yilishi haqidagi bo'limda ko'rdik.
Ikki yechim bor:
const shablon = "Izoh: {matn}";
const izoh = "Chegirma $& bonus";
console.log(shablon.replace("{matn}", () => izoh));
console.log(shablon.replace("{matn}", izoh.replaceAll("$", "$$$$")));Konsolda:
Izoh: Chegirma $& bonus
Izoh: Chegirma $& bonusBirinchisi — funksiya: u qaytargan matn tekshirilmaydi, so'zma-so'z qo'yiladi. Ikkinchisi — har $ ni $$ ga aylantirish. "$$$$" to'rtta dollar, chunki u ham almashtirish matni: har $$ bitta $ beradi. Ko'rinib turibdiki, ikkinchisini o'qish qiyin. Shuning uchun qoida sodda: tashqaridan kelgan matn bilan almashtirsangiz — funksiya bering.
Tekshirib ko'ring:
new RegExp(RegExp.escape("osh(")).test("Bugun osh(palov)")nima qaytaradi? Escape bo'lmasa-chi?
Javob
Escape bilan — true: naqsh aynan osh( matnini qidiradi va u matnda bor. Escape'siz new RegExp("osh(") umuman yaratilmaydi — SyntaxError: ... Unterminated group. Ochiluvchi qavs guruh boshi deb tushuniladi.
6. Hujumchi nigohi
Dinamik regex — foydalanuvchi matni kodga aylanadigan joy. Bunday joylar har doim hujumchini qiziqtiradi. Escape'siz qidiruvni qanday buzishga urinishadi?
- Xato bilan yiqitish.
(,[,\kabi bitta belgiSyntaxErrorberadi. Qidiruv funksiyasitry/catchsiz bo'lsa, sahifa yoki server so'rovi to'xtaydi. Bu eng yengil holat. - Hamma narsani topish.
.*deb yozilsa, regex har qanday matnga mos keladi. Agar regex "shu foydalanuvchiga tegishli yozuvlar" kabi filtrda ishlatilsa, hujumchi begona ma'lumotni ko'rishi mumkin. - Qotirish. Eng xavflisi — ataylab "og'ir" naqsh yuborish.
(a+)+$kabi naqsh qisqa matnda ham dvigatelni soniyalab, hatto daqiqalab band qiladi. Node'da bu butun server bitta so'rov tufayli boshqalarga javob bermay qoladi degani. Bu hujum ReDoS deb ataladi, uni keyingi darsda o'lchaymiz.
Darsdagi kod bularga qanday qarshi turadi? RegExp.escape dan keyin foydalanuvchi matnidagi birorta ham belgi buyruq emas. (a+)+$ endi oddiy matn — "aynan (a+)+$ belgilarini qidir". Naqshning shakli — bizniki, foydalanuvchi faqat qidiriladigan matnni beradi.
Qo'shimcha himoya:
- Uzunlik chegarasi. Qidiruv so'zi 100 belgidan oshmasin. HTML'da —
maxlength, JavaScript'da —soz.lengthtekshiruvi. - Kerak bo'lmasa — regex yo'q. Faqat "shu so'z bormi?" kerak bo'lsa,
matn.toLowerCase().includes(soz.toLowerCase())yetadi. Unda escape ham kerak emas. - Foydalanuvchiga naqsh yozdirmang. "Rivojlangan qidiruv" uchun foydalanuvchining o'z regex'i kerak bo'lsa ham, uni serverda ishlatmang. Bunday hollarda xavfsiz regex dvigatellari ishlatiladi — keyingi darsda.
7. Ko'p uchraydigan xatolar
7.1 Naqshga qavs qo'shib, $1 ni unutish
Naqsh (\d{4})-(\d{2}) edi, keyin boshiga yana bitta guruh qo'shildi. Endi $1 boshqa narsani bildiradi, xato esa chiqmaydi. Tuzatish: guruh ko'p bo'lsa — nomlangan guruh va $<nom>. Faqat guruhlash kerak bo'lsa — ushlamaydigan (?:...).
7.2 Shablon satrda $ bilan adashish
Almashtirish matnini shablon satrda (backtick) yozsangiz, $1 va $<nom> muammosiz ishlaydi. Lekin ${1} — bu JavaScript'ning o'z qo'shimchasi, regex guruhi emas:
const sana = "2026-10-05";
console.log(sana.replace(/(\d{4})-(\d{2})-(\d{2})/, `$3.$2.$1`));
console.log(sana.replace(/(\d{4})-(\d{2})-(\d{2})/, `${3}.$2.$1`));Konsolda:
05.10.2026
3.10.2026Ikkinchi qatorda ${3} JavaScript ifodasi sifatida bajarildi — natija oddiy 3 raqami. Tuzatish: almashtirish matnini oddiy qo'shtirnoqda yozing yoki ${ dan qoching.
7.3 Callback'da return yo'q
Jingalak qavsli arrow funksiyada return ni unutsangiz, har moslik o'rniga undefined so'zi chiqadi. Tuzatish: (m) => m.toUpperCase() kabi qisqa shakl yoki aniq return.
7.4 Butun naqshni escape qilish
const naqsh = new RegExp(RegExp.escape("\\d+"));
console.log(naqsh.test("Osh 35000")); // false
console.log(naqsh.test("\\d+ belgisi")); // trueRegExp.escape sizning \d+ ingizni ham "oddiy matn" qildi — endi u teskari chiziq, d va plyusni qidiradi. Tuzatish: escape faqat tashqaridan kelgan bo'lakka.
7.5 Escape'ni unutish
new RegExp(soz) — har safar xavf. Bugun soz o'zingiz yozgan ro'yxatdan kelyapti, ertaga esa kimdir uni formaga ulaydi. Tuzatish: new RegExp ga o'zgaruvchi berilsa, uni odat qilib RegExp.escape dan o'tkazing.
O'zingiz to'ldiring: almashtirish matnida nomli guruh oy ni deb chaqirasiz.
8. Mashqlar
1-mashq (oson): Sana formati
sananiFormatla(matn) matndagi hamma YYYY-MM-DD sanalarni DD.MM.YYYY ko'rinishiga keltirsin. Nomlangan guruhlar va $<nom> dan foydalaning.
console.log(sananiFormatla("Bron: 2026-10-05, keyingisi 2026-10-12"));
// Bron: 05.10.2026, keyingisi 12.10.2026Yechim
function sananiFormatla(matn) {
return matn.replace(
/(?<yil>\d{4})-(?<oy>\d{2})-(?<kun>\d{2})/g,
"$<kun>.$<oy>.$<yil>",
);
}
console.log(sananiFormatla("Bron: 2026-10-05, keyingisi 2026-10-12"));Konsolda:
Bron: 05.10.2026, keyingisi 12.10.2026g flagi bo'lmasa, faqat birinchi sana almashardi. Sananing to'g'riligini (13-oy yo'qligini) regex tekshirmaydi — sanalar bilan ishlashni Date asoslari darsidan boshlab o'rganamiz.
2-mashq (o'rta): Telefon — bitta replace bilan
Belgilar va belgi klasslari darsida telefonni slice bilan bo'laklagan edik. Endi telefonniFormatla(raqamlar) 12 ta raqamdan iborat satrni ("998900000000") guruhlar bilan bitta replace da +998 90 000 00 00 ko'rinishiga keltirsin. Ishora: besh guruh — 3, 2, 3, 2, 2 raqam; ^ va $ bilan.
console.log(telefonniFormatla("998900000000")); // +998 90 000 00 00
console.log(telefonniFormatla("99890")); // 99890Yechim
function telefonniFormatla(raqamlar) {
return raqamlar.replace(
/^(\d{3})(\d{2})(\d{3})(\d{2})(\d{2})$/,
"+$1 $2 $3 $4 $5",
);
}
console.log(telefonniFormatla("998900000000")); // +998 90 000 00 00
console.log(telefonniFormatla("99890")); // 99890Raqam soni noto'g'ri bo'lsa, naqsh mos kelmaydi va replace matnni o'zgartirmasdan qaytaradi. Bu foydali xulq: noto'g'ri raqam "chiroyli" ko'rinishga kelib, to'g'ri deb o'ylanmaydi.
3-mashq (qiyin): Qidiruv natijasini belgilash
belgila(matn, soz) matndagi soz ning hamma uchrashuvlarini (harf kattaligiga qaramay) kvadrat qavsga olsin: [1.5]. So'z bo'sh yoki faqat bo'sh joydan iborat bo'lsa — matn o'zgarmasin. Ishora: RegExp.escape, g va i flaglari, almashtirish uchun funksiya (topilgan bo'lakni asl yozuvida qaytarish uchun).
console.log(belgila("1.5 kg guruch, 125 g sariyog'", "1.5"));
// [1.5] kg guruch, 125 g sariyog'
console.log(belgila("Osh (katta), osh (kichik)", "osh ("));
// [Osh (]katta), [osh (]kichik)Yechim
function belgila(matn, soz) {
if (soz.trim() === "") {
return matn;
}
const naqsh = new RegExp(RegExp.escape(soz), "giu");
return matn.replace(naqsh, (topilgan) => `[${topilgan}]`);
}
console.log(belgila("1.5 kg guruch, 125 g sariyog'", "1.5"));
console.log(belgila("Osh (katta), osh (kichik)", "osh ("));
console.log(belgila("Narx $5", "$5"));
console.log(belgila("Osh", " "));Konsolda:
[1.5] kg guruch, 125 g sariyog'
[Osh (]katta), [osh (]kichik)
Narx [$5]
OshFunksiya kerak edi, chunki i flagi bilan Osh ham, osh ham topiladi — ularni asl yozuvida qaytarish kerak. "[$&]" ham shuni qilardi. Lekin funksiya bilan qoida bitta: tashqaridan kelgan narsa bilan almashtirganda $ belgilari hech qachon ishlamaydi. Bo'sh so'z tekshiruvi ham muhim: bo'sh naqsh har belgi orasida bo'sh moslik beradi va matnni [] larga to'ldirib yuboradi.
4-mashq: Vazifalar qadami — vazifa matnini tozalash
Vazifa matniga foydalanuvchilar Telegram yoki Word'dan nusxa qo'yadi. Unda "chiroyli" apostroflar (ʻ, ’, ‘) va ketma-ket bo'sh joylar keladi. Natijada do'kon va do’kon ikki xil teg bo'lib qoladi. Shu muammoni hal qiling. Faylni kurs/mashqlar/12/09-tozalash/tozala.mjs da yarating. Undagi matnniTozala(matn) funksiyasi hamma apostrof variantlarini oddiy ' ga aylantirsin. Har qanday bo'sh joylar ketma-ketligi bitta bo'sh joy bo'lsin, chetlari esa kesilsin. vazifalar kodini hozircha o'zgartirmang — bu mashq faylida.
Ishora: apostroflarni kodlari bilan yozing — \u{2BB} (ʻ), \u{2018} (‘), \u{2019} (’). Bu yozuv u flagi bilan ishlaydi.
Yechim
const APOSTROFLAR = /[\u{2BB}\u{2018}\u{2019}`]/gu;
function matnniTozala(matn) {
return matn.replace(APOSTROFLAR, "'").replace(/\s+/g, " ").trim();
}
const kiritilgan = " Non olish #do\u{2019}kon #o\u{2BB}quv ";
const toza = matnniTozala(kiritilgan);
console.log(JSON.stringify(toza));
console.log(toza.includes("#do'kon")); // trueKonsolda:
"Non olish #do'kon #o'quv"
trueIkki replace zanjirda ishladi: avval apostroflar, keyin bo'sh joylar. Backtick ham klassga qo'shildi — u ham ba'zan apostrof o'rnida yoziladi. JSON.stringify natijani qo'shtirnoq ichida chiqardi — chetlarda bo'sh joy qolmagani ko'rinib turibdi. Bu funksiyani vazifalar ga qo'shish — ilovaning xulqini o'zgartiradi, shuning uchun hozircha alohida faylda turadi.
git add 12/09-tozalash/tozala.mjs
git commit -m "12/09: apostrof va bo'sh joylarni tozalash"9. Real ishda
- Ma'lumotni formatlash. Sana, telefon, karta raqamining oxirgi to'rt raqami, summa — ko'rsatishdan oldin
replaceva guruhlar bilan bir xil ko'rinishga keltiriladi. - Qidiruv va belgilash. Onlayn do'konlardagi qidiruv natijasida topilgan so'z ajratib ko'rsatiladi — ichida xuddi
belgilakabi kod bor. Brauzerda natija<mark>tegi bilan chiqariladi,innerHTMLemas, DOM orqali (Kontentni o'zgartirish va XSS xavfi). - Shablonlar. SMS va email matnlaridagi
{ism},{summa}kabi joylarreplaceva funksiya bilan to'ldiriladi. Mijoz ismi$bilan boshlansa ham buzilmasligi uchun aynan funksiya ishlatiladi. - Kod vositalari. VS Code'dagi "Find and Replace" regex rejimida
$1va$<nom>ni tushunadi. Ko'p faylda nomni o'zgartirish shunday qilinadi. - Intervyu. "
replacega funksiya berish nima uchun kerak?", "$1nima?", "Foydalanuvchi matnidan regex qanday xavfsiz yasaladi?" — tez-tez so'raladi.
Xulosa
- Almashtirish matnida:
$&— moslik,$1— raqamli guruh,$<nom>— nomli guruh,$`va$'— oldingi va keyingi matn,$$— dollar. - Mavjud bo'lmagan guruh jimgina oddiy matn yoki bo'sh satr bo'lib qoladi — natijani konsolda tekshiring.
- Funksiya bilan almashtirish — hisob kerak bo'lganda; argumentlar: moslik, guruhlar, indeks, matn,
groups. Qaytargani so'zma-so'z qo'yiladi. replaceAllsatr bilan — so'zma-so'z; regex bilan faqatgflagi bilan.- Foydalanuvchi matnidan regex — faqat
RegExp.escape(matn)orqali (Baseline 2025); escape faqat tashqaridan kelgan bo'lakka. - Tashqaridan kelgan matn bilan almashtirsangiz —
replace(naqsh, () => matn).
Keyingi dars: Regex amaliyotda va ReDoS — email va telefon tekshiruvining chegaralari, regex qachon kerak emasligi va yomon naqsh serverni qanday "qotirishini" o'lchab ko'ramiz.
Manbalar
- MDN: "String.prototype.replace" (Specifying a string as the replacement, Specifying a function as the replacement), "String.prototype.replaceAll", "RegExp.escape()" — developer.mozilla.org
- ECMAScript 2026: GetSubstitution, RegExp.escape — tc39.es/ecma262; taklif: github.com/tc39/proposal-regex-escaping
- web-features 3.40.0:
regexp-escape— Baseline 2025-05-01 (Chrome 136, Firefox 134, Safari 18.2)
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!