IlmHamroh
JavaScript Full-stack/12-qism. JavaScript: ilg'or mavzular va kod sifati6/44-dars18 daqiqa
Mundarija (32)

Regex flaglari: g i m s u v y d va lastIndex tuzog'i

Qisqacha: Flaglar regex'ning ishlash tartibini o'zgartiradi. Ular: g — hammasi, i — harf kattaligi farqsiz, m — har qator, s — nuqta yangi qatorni ham oladi. Yana: u/v — Unicode rejimi, y — aynan shu joydan, d — guruhlarning o'rni. Flagi g yoki y bo'lgan regex lastIndex da qayerda to'xtaganini eslab qoladi. Shuning uchun bitta regex bilan test ni qayta-qayta chaqirsangiz, natija "sakraydi". Qoida: test uchun g qo'ymang.

Bu darsda

  • Sakkizta flagning har biri nima qilishini va qachon kerakligini bilasiz.
  • s bilan ko'p qatorli matndan bo'lak olasiz, y bilan matnni chapdan o'ngga bo'laklab o'qiysiz.
  • d flagi bilan guruhlar matnning qaysi o'rnida turganini olasiz.
  • lastIndex nima ekanini va g bilan test nega true, false deb almashishini qadamma-qadam tushuntira olasiz.
  • Naqshning faqat bir qismiga flag berasiz: (?i:...).

Oldin bilishingiz kerak: RegExp asoslari va metodlari, Langarlar va so'z chegarasi, Guruhlar va alternation.

1. Nega bu kerak?

Sardor «Bahor» saytiga menyu qidiruvini qo'shdi. Mehmon osh deb yozsa, nomida osh bor taomlar chiqishi kerak. Katta-kichik harf farqlanmasin — demak i. "Hammasini topsin" deb g ham qo'shdi:

js
const naqsh = /osh/gi;
const taomlar = ["Osh", "Oshqovoq somsa", "Manti", "To'y oshi"];

console.log(taomlar.filter((taom) => naqsh.test(taom)));
// [ 'Osh', "To'y oshi" ]

Oshqovoq somsa qayerga ketdi? Unda Osh bor-ku. g ni olib tashlasa — uchala taom ham chiqadi. Kod xato bermaydi, faqat ba'zan noto'g'ri natija beradi. Bunday xato eng qiyini: sinovda ishlaydi, mijozda esa yo'q.

Sababi — g flagining yashirin xotirasi, lastIndex. Bugun shuni ochamiz. Lekin avval flaglarning hammasi bilan tanishamiz: RegExp asoslari darsida "qolganlarini keyin o'rganamiz" degan edik.

2. Flaglar: umumiy ko'rinish

2.1 Sakkizta flag

Flag (flag — "bayroqcha") — regex oxiridagi harf. U butun naqshning ishlash tartibini o'zgartiradi. Telefon kamerasidagi rejimlarni eslang: linza bitta, lekin "tun" yoki "portret" rejimida surat boshqacha chiqadi. Naqsh ham bitta, flag esa uni qanday qidirishini belgilaydi. JavaScript'da hammasi bo'lib sakkizta flag bor:

Flag To'liq nomi Nima qiladi
g global birinchisida to'xtamaydi, hammasini topadi
i ignoreCase A va a bir xil
m multiline ^ va $ har qator boshi va oxiri
s dotAll . yangi qatorni ham oladi
u unicode Unicode rejimi, qat'iy sintaksis
v unicodeSets u ning yangi, kengroq varianti
y sticky moslik aynan lastIndex joyidan boshlanishi shart
d hasIndices guruhlarning boshlanish va tugash o'rni

Uchtasini bilasiz: g va i — RegExp asoslari darsidan, m — Langarlar darsidan.

2.2 Flaglarni koddan o'qish

Har flagning regex obyektida o'z xususiyati bor — jadvaldagi ikkinchi ustun. Hammasi birga flags satrida:

js
const naqsh = /osh/gi;

console.log(naqsh.flags); // gi
console.log(naqsh.global); // true
console.log(naqsh.ignoreCase); // true
console.log(naqsh.multiline); // false

Flaglar qaysi tartibda yozilganining farqi yo'q. flags esa ularni doim bir xil — alifbo — tartibda qaytaradi:

js
console.log(new RegExp("a", "yigd").flags); // dgiy

Bu xususiyatlar faqat o'qish uchun. Regex yaratilgandan keyin flagini o'zgartirib bo'lmaydi. Boshqa flag kerak bo'lsa — yangi regex: new RegExp(naqsh.source, "g").

2.3 Noto'g'ri flag

Bir flagni ikki marta yozsangiz yoki mavjud bo'lmagan harf bersangiz, JavaScript xato beradi:

js
const naqsh = new RegExp("osh", "gg");
text
SyntaxError: Invalid flags supplied to RegExp constructor 'gg'

Tarjimasi: "RegExp konstruktoriga noto'g'ri flaglar berildi: 'gg'." Boshqa tillardan ko'chirilgan x flagi ham shunday xato beradi — JavaScript'da u yo'q. Literalda (/osh/x) xabar qisqaroq: Invalid regular expression flags. U kod ishga tushishidan oldin, fayl o'qilayotganda chiqadi.

Tekshirib ko'ring: /bahor/mi.flags nima qaytaradi?

Javob

"im". flags har doim flaglarni bir xil tartibda beradi: d g i m s u v y. Siz mi deb yozgan bo'lsangiz ham.

3. s — nuqta yangi qatorni ham oladi

Belgilar va belgi klasslari darsida . "istalgan belgi, faqat yangi qatordan boshqa" degan edik. Bu ko'pincha qulay: bitta qator ichida qoladi. Lekin ba'zan matn bir necha qatorga cho'zilgan bo'ladi.

Bron formasidagi izoh ikki qatorga yozildi. Sardor Izoh: dan Tel gacha hammasini olmoqchi:

js
const forma =
  "Izoh: piyozsiz,\nachchiq bo'lmasin.\nTel: +998 90 000 00 00";

console.log(forma.match(/Izoh: (.+)/)[1]); // piyozsiz,
console.log(forma.match(/Izoh: (.+?)\nTel/s)[1]);

Konsolda:

text
piyozsiz,
piyozsiz,
achchiq bo'lmasin.

Birinchi naqsh qator oxirida to'xtadi: . \n ni o'tkazmaydi. Ikkinchisida s flagi (dotAll — "nuqta hammasi") bor: . endi yangi qatorni ham oladi. Dangasa +? esa birinchi \nTel da to'xtatdi.

Maydonda sinang:

m va s ni adashtirmang. m — langarlarga (^, $) tegishli, s — nuqtaga. Ikkalasi bir-biridan mustaqil va birga ham ishlatiladi.

Eski kodda s o'rniga [\s\S] yozuvini uchratasiz: "bo'sh joy yoki bo'sh joy bo'lmagan belgi", ya'ni istalgan belgi. s flagi 2018-yilda qo'shilgan, undan oldin shunday yozishardi.

O'zingiz to'ldiring: ^ va $ ni har qator uchun ishlatadigan flag — m, nuqtani yangi qatordan o'tkazadigan flag esa — .

4. u va v — Unicode rejimi

Bu ikki flag regex'ni Unicode rejimiga o'tkazadi. Ikkita asosiy ta'siri bor.

Birinchisi — qat'iy sintaksis. Quantifierlar darsida /a{,3}/ jimgina oddiy matnga aylangan edi, u bilan esa xato bergan. Unicode rejimida noma'lum escape va chala yozuvlar xato bo'ladi — ular kod ichida yashirinib qolmaydi.

Ikkinchisi — emoji va boshqa "katta" belgilar. Unicode va emoji darsidan eslang: ba'zi belgilar JavaScript satrida ikki bo'lak bo'lib saqlanadi ("😀".length — 2). u siz . ularni ikkiga bo'lib yuboradi:

js
console.log("😀".match(/./g).length); // 2
console.log("😀".match(/./gu).length); // 1

v — u ning 2023-yilda chiqqan, kengroq varianti. Mobil klaviatura darsida eslatgan edik: HTML pattern atributi naqshni aynan v flagi bilan tekshiradi. u va v ni birga yozib bo'lmaydi — Invalid flags xatosi chiqadi.

Ikkalasining hamma imkoniyatlari — har qanday alifbodagi harf \p{L}, emoji, to'plamlar — Unicode regex: u va v flag darsida. Hozircha bitta qoida: yangi yozilayotgan regex'da u yoki v qo'yish — yaxshi odat.

5. lastIndex — regex'ning xotirasi

5.1 Qayerda to'xtadim?

RegExp asoslari darsida exec ni while siklida ishlatgan edik. U har chaqiruvda keyingi moslikni berardi. Buning uchun regex qayerda to'xtaganini eslab qolishi kerak. U shu joyni lastIndex ("oxirgi indeks") xususiyatida saqlaydi.

Kitobdagi xatcho'pni eslang: o'qishni to'xtatsangiz, xatcho'p keyingi safar qayerdan boshlashni ko'rsatadi. lastIndex — regex'ning xatcho'pi. Faqat bitta farq bor, va tuzoq aynan shunda: xatcho'p kitobga (matnga) emas, regex'ga qistirilgan.

lastIndex — oddiy son. Regex g yoki y flagli bo'lsa, test va exec:

  1. qidiruvni lastIndex o'rnidan boshlaydi;
  2. moslik topsa — lastIndex ni moslikdan keyingi o'ringa suradi;
  3. topmasa — lastIndex ni 0 ga qaytaradi.

g yoki y bo'lmasa, lastIndex e'tiborga olinmaydi — qidiruv har doim boshidan.

js
const naqsh = /osh/g;

console.log(naqsh.test("osh osh"), naqsh.lastIndex); // true 3
console.log(naqsh.test("osh osh"), naqsh.lastIndex); // true 7
console.log(naqsh.test("osh osh"), naqsh.lastIndex); // false 0
console.log(naqsh.test("osh osh"), naqsh.lastIndex); // true 3

Bir xil matn, bir xil regex — lekin natija true, true, false, true. Uchinchi chaqiruv 7-o'rindan qidirdi — u yerda matn tugagan.

5.2 Tuzoq qadamma-qadam

Endi «Nega bu kerak?» bo'limidagi qidiruvga qaytamiz. Regex bitta, matnlar esa har xil. lastIndex esa bir matndan ikkinchisiga o'tib ketadi. O'ngdagi bo'limda uning har qadamdagi qiymatiga qarang:

Asosiy g'oya: lastIndex — matnga emas, regex obyektiga tegishli. Regex esa bitta. Xuddi bitta xatcho'pni bir kitobdan olib, ikkinchi kitobning 3-sahifasiga qo'yganday. filter uni to'rt marta, to'rt xil matn bilan chaqirdi — oldingi chaqiruvning "izi" keyingisiga o'tdi.

Natija taomlar tartibiga bog'liq. Ro'yxatda Oshqovoq somsa birinchi tursa, xato boshqa joyda chiqadi. Shuning uchun bunday xatoni topish qiyin.

5.3 Uchta yechim

1. test uchun g qo'ymang. Eng oddiy va eng to'g'ri yo'l. "Bormi?" degan savolga g kerak emas:

js
const naqsh = /osh/i;
const taomlar = ["Osh", "Oshqovoq somsa", "Manti", "To'y oshi"];

console.log(taomlar.filter((taom) => naqsh.test(taom)));
// [ 'Osh', 'Oshqovoq somsa', "To'y oshi" ]

2. Regex'ni ishlatiladigan joyda yarating. Funksiya ichida yozilgan literal har chaqiruvda yangi obyekt, lastIndex esa yangi 0:

js
function oshBormi(taom) {
  return /osh/gi.test(taom);
}

const taomlar = ["Osh", "Oshqovoq somsa", "Manti", "To'y oshi"];
console.log(taomlar.filter(oshBormi));
// [ 'Osh', 'Oshqovoq somsa', "To'y oshi" ]

Lekin bu yechim nozik: kimdir keyin regex'ni funksiyadan tashqariga chiqarsa, xato qaytadi.

3. lastIndex ni qo'lda nolga qaytaring. naqsh.lastIndex = 0 — exec sikli oldidan. Bu g haqiqatan kerak bo'lgan joylar uchun.

Diqqat: Tuzoq faqat test da emas. exec ham lastIndex dan foydalanadi. g flagli regex'ni modul darajasida (fayl tepasida) e'lon qilib, uni turli funksiyalarda exec yoki test bilan ishlatish — eng xavfli kombinatsiya.

5.4 Qaysi metod lastIndex ga qaraydi

Satr metodlari bu tuzoqdan deyarli himoyalangan, lekin har biri o'zicha ishlaydi:

Metod (g bilan) lastIndex dan boshlaydimi Keyin lastIndex
test, exec ha suriladi yoki 0
match, replace yo'q, 0 dan 0
search yo'q, 0 dan o'zgarmaydi
matchAll ha (nusxasi) o'zgarmaydi

Oxirgi qator kutilmagan. matchAll regex'ning nusxasini yaratadi, lekin nusxa asl regex'ning lastIndex idan boshlaydi:

js
const naqsh = /\d+/g;
naqsh.lastIndex = 5;

const hammasi = [..."12 34 56".matchAll(naqsh)];

console.log(hammasi.map((m) => m[0])); // [ '56' ]
console.log("12 34 56".match(naqsh)); // [ '12', '34', '56' ]

match hammasini topdi, matchAll esa faqat 5-o'rindan keyingisini. Kundalik kodda bu kam uchraydi, lekin exec sikli bilan bir regex'ni bo'lishsangiz — paydo bo'ladi.

Tekshirib ko'ring: const r = /a/g; dan keyin r.test("a") ikki marta chaqirildi. Natijalar qanday? r ni /a/ deb yozsak-chi?

Javob

g bilan — true, keyin false. Birinchi chaqiruv lastIndex ni 1 ga surdi, ikkinchisi 1-o'rindan qidirdi — u yerda matn tugagan. g siz — ikkalasi ham true: lastIndex e'tiborga olinmaydi.

O'zingiz to'ldiring: g flagli regex keyingi qidiruv qayerdan boshlanishini xususiyatida saqlaydi.

6. y — aynan shu joydan

6.1 Yopishqoq qidiruv

y flagi (sticky — "yopishqoq") ham lastIndex dan foydalanadi, lekin qat'iyroq. Yopishqoq lentani eslang: u aynan bosgan joyingizga yopishadi, bir santimetr ham surilmaydi. g lastIndex dan keyin istalgan joyda qidiradi. y esa moslik aynan lastIndex o'rnidan boshlanishini talab qiladi. Bir qadam ham chetga chiqmaydi.

js
const naqsh = /\d+/y;

console.log(naqsh.test("Osh 35000")); // false
naqsh.lastIndex = 4;
console.log(naqsh.exec("Osh 35000")[0]); // 35000

Birinchi test 0-o'rinda raqam kutdi, u yerda esa O. g bo'lganda 35000 ni topardi. lastIndex ni 4 ga qo'yganimizdan keyin — aynan shu o'rinda son bor.

Farqni maydonda ko'ring. gy birga — "aynan shu joydan, ketma-ket, uzilish bo'lguncha":

6.2 Nega kerak: matnni bo'laklab o'qish

y matnni chapdan o'ngga, bo'lakma-bo'lak "yeb" boradigan dasturlar uchun yaratilgan. Masalan, kalkulyator 35000 + 5000*2 ifodasini avval sonlar va amallarga bo'ladi. Bunday bo'laklar token deb ataladi.

Nega g yetmaydi? Chunki g tushunmagan belgini jimgina o'tkazib yuboradi:

js
console.log("35000 / 2".match(/\d+|[+*-]/g)); // [ '35000', '2' ]

/ belgisi yo'qoldi, xato ham chiqmadi. Kalkulyator 35000 2 ni hisoblashga urinadi. y bilan esa har bir belgi biror bo'lakka tushishi shart. Tushmasa — biz xatoni darhol bilamiz. Buni 3-mashqda yozasiz.

7. d — guruhlarning o'rni

match natijasidagi index faqat butun moslik qayerdan boshlanganini aytadi. Guruhlar qayerda? d flagi (hasIndices — "indekslar bor") natijaga indices xususiyatini qo'shadi: har guruhning [boshi, oxiri] juftligi.

js
const bron = "Bron: 19:30 da";
const naqsh = /(?<soat>\d{2}):(?<daqiqa>\d{2})/d;
const moslik = bron.match(naqsh);

console.log(moslik.indices[0]); // [ 6, 11 ]
console.log(moslik.indices.groups.soat); // [ 6, 8 ]
console.log(moslik.indices.groups.daqiqa); // [ 9, 11 ]

[6, 11] — butun 19:30 6-o'rindan boshlanib, 11-o'rindan oldin tugaydi. Bu slice(6, 11) ga to'g'ri keladi. Soat — [6, 8], daqiqa — [9, 11].

Qayerda kerak? Matnning bir qismini ajratib ko'rsatishda: kod muharririda xato joyini qizil chiziq bilan belgilash, qidiruv natijasida topilgan so'zni sariq qilish. Shu darsdagi regex maydoni ham guruhlarni aynan shu ma'lumot bilan bo'yaydi. Flaglar katagiga d yozing — jadvalda guruhlarning o'rni paydo bo'ladi:

d ni faqat kerak bo'lganda qo'ying: u har moslik uchun qo'shimcha massivlar yasaydi va regex'ni biroz sekinlashtiradi.

8. Naqshning bir qismiga flag: (?i:...)

Ba'zan flag butun naqshga emas, faqat bir bo'lagiga kerak. «Bahor» tizimida buyurtma kodi BHR- bilan boshlanadi — bu qism doim katta harfda. Keyingi so'z esa — taom nomi — har xil yozilishi mumkin: Osh, OSH, osh.

ES2025 standartida inline modifikator qo'shildi: (?i:...) — "faqat shu qavs ichida i flagi ishlasin":

js
const kod = /^BHR-(?i:osh|manti)$/;

console.log(kod.test("BHR-OSH")); // true
console.log(kod.test("BHR-Manti")); // true
console.log(kod.test("bhr-osh")); // false

Teskarisi ham bor: (?-i:...) — butun regex i bilan bo'lsa ham, shu qism harf kattaligini farqlaydi. Faqat uchta flagni shunday ishlatish mumkin: i, m va s. (?g:...) kabi boshqa flag — Invalid group xatosi.

Bu yangi imkoniyat: Chrome 125, Firefox 132, Safari 26 va Node 23 dan beri bor (MDN ma'lumotlari, 2026-yil oktabr holati). Eski telefonlarda bunday regex fayldagi butun skriptni ishlatmay qo'yishi mumkin. Brauzer mosligini tekshirish yo'llari — JS versiyalari va brauzer mosligi darsida.

9. Ko'p uchraydigan xatolar

9.1 test va g

/.../g.test(...) ni bir regex bilan qayta-qayta chaqirish — natija lastIndex ga qarab "sakraydi". Tuzatish: test uchun g qo'ymang.

9.2 g flagli regex'ni ulashish

Fayl tepasida const NAQSH = /.../g; va uni bir nechta funksiyada exec bilan ishlatish. Bir funksiya lastIndex ni o'zgartiradi, ikkinchisi o'rtadan qidiradi. Tuzatish: exec siklidan oldin NAQSH.lastIndex = 0 yoki matchAll.

9.3 m va s ni adashtirish

"Ko'p qatorli matn" degani m emas. m — faqat ^ va $ uchun. Nuqtani qatorlardan o'tkazish — s. Tuzatish: nima kerakligini aniqlang: langarmi yoki nuqta.

9.4 Boshqa tilning flagi

Python va PHP'dagi x (izohli naqsh) yoki ba'zi tillardagi U JavaScript'da yo'q — SyntaxError. Internetdan regex ko'chirsangiz, flaglarini tekshiring.

9.5 Flagni o'zgartirishga urinish

Flag xususiyatlari faqat o'qish uchun. Qat'iy rejimda (strict mode — modulda, .mjs faylda va saytdagi «Ishga tushir» tugmasida ham) ularga qiymat berish xato beradi:

js
const naqsh = /osh/g;
naqsh.global = false;
text
TypeError: Cannot set property global of [object Object] which has only a getter

Tarjimasi: "global xususiyatiga qiymat berib bo'lmaydi — unda faqat o'qish usuli (getter) bor." [object Object] — bu bizning regex: Node xabarda uni shunday umumiy nom bilan ko'rsatadi. Qat'iy bo'lmagan oddiy skriptda esa xato ham chiqmaydi — qiymat jimgina o'zgarmay qoladi. Tuzatish: yangi regex — new RegExp(naqsh.source, "i").

10. Mashqlar

1-mashq (oson): Flaglarni tanlang

Har vazifa uchun naqsh va flaglarni yozing, keyin console.log bilan tekshiring:

  1. "OSH, osh, Osh" matnidagi hamma osh larni sanang (natija: 3).
  2. "Menyu:\nOsh\nManti" matnida Menyu: dan oxirigacha hammasini oling.
js
console.log("OSH, osh, Osh".match(/* ? */).length); // 3
Yechim
js
console.log("OSH, osh, Osh".match(/osh/gi).length); // 3

const matn = "Menyu:\nOsh\nManti";
console.log(JSON.stringify(matn.match(/Menyu:.+/s)[0]));
// "Menyu:\nOsh\nManti"

Birinchisiga ikki flag kerak: g — hammasi, i — harf kattaligiga qarama. Ikkinchisida s — . yangi qatorlardan o'tadi. JSON.stringify natijani \n lari bilan bitta qatorda ko'rsatdi.

2-mashq (o'rta): Qidiruvni tuzating

Quyidagi kod mehmonlar izohlaridan telefon raqami bor izohlarni tanlashi kerak edi. Bittasi yo'qoladi. Qaysi biri va nega? Tuzating.

js
const telBor = /\+998/g;
const izohlar = ["+998 90 000 00 00", "+998 91 000 00 00", "Deraza"];

console.log(izohlar.filter((izoh) => telBor.test(izoh)));
Yechim
js
const telBor = /\+998/g;
const izohlar = ["+998 90 000 00 00", "+998 91 000 00 00", "Deraza"];

console.log(izohlar.filter((izoh) => telBor.test(izoh)));

const telBorTogri = /\+998/;
console.log(izohlar.filter((izoh) => telBorTogri.test(izoh)));

Konsolda:

text
[ '+998 90 000 00 00' ]
[ '+998 90 000 00 00', '+998 91 000 00 00' ]

Birinchi izohdan keyin lastIndex 4 bo'ldi. Ikkinchi izoh 4-o'rindan qidirildi va uning boshidagi +998 o'tkazib yuborildi. g siz lastIndex e'tiborga olinmaydi — har izoh boshidan tekshiriladi.

3-mashq (qiyin): Kalkulyator uchun bo'laklar

tokenlarga(ifoda) — "35000 + 5000*2" kabi matnni sonlar va amallar massiviga aylantirsin: [35000, '+', 5000, '*', 2]. Bo'sh joylar tashlab ketilsin. Tanilmagan belgi uchrasa — Error tashlansin, xabarida o'rni bilan. Ishora: y flagi, uchta nomli guruh (son, amal, bosh) va |; sikl lastIndex matn uzunligiga yetguncha.

js
console.log(tokenlarga("35000 + 5000*2"));
// [ 35000, '+', 5000, '*', 2 ]
tokenlarga("35000 / 2"); // Error: 6-o'rinda noma'lum belgi: /
Yechim
js
function tokenlarga(ifoda) {
  const naqsh = /(?<son>\d+)|(?<amal>[+*-])|(?<bosh>\s+)/y;
  const tokenlar = [];
  while (naqsh.lastIndex < ifoda.length) {
    const joy = naqsh.lastIndex;
    const moslik = naqsh.exec(ifoda);
    if (!moslik) {
      throw new Error(`${joy}-o'rinda noma'lum belgi: ${ifoda[joy]}`);
    }
    const { son, amal } = moslik.groups;
    if (son) {
      tokenlar.push(Number(son));
    } else if (amal) {
      tokenlar.push(amal);
    }
  }
  return tokenlar;
}

console.log(tokenlarga("35000 + 5000*2"));

try {
  tokenlarga("35000 / 2");
} catch (xato) {
  console.log(xato.message);
}

Konsolda:

text
[ 35000, '+', 5000, '*', 2 ]
6-o'rinda noma'lum belgi: /

Har exec aynan lastIndex dan boshlab bitta bo'lakni oladi va lastIndex ni surib qo'yadi. / hech qaysi variantga mos kelmadi — y uni o'tkazib yubormadi, exec null qaytardi. Regex funksiya ichida yaratilgan — har chaqiruvda lastIndex yangi 0. [+*-] da chiziqcha oxirida, shuning uchun diapazon emas (Belgilar va belgi klasslari darsidan).

4-mashq: Vazifalar qadami — qidiruv "sakramasin"

vazifalar ga kelajakda qidiruv maydoni qo'shilsa, kimdir shunday yozishi mumkin: regex fayl tepasida, g va i bilan. kurs/mashqlar/12/06-qidiruv/qidiruv.mjs da bu xatoni takrorlang: bir xil qidiruvni ikki marta chaqiring va natijalarni solishtiring. Keyin tuzating: qidir(royxat, soz) regex'ni o'zi i bilan yaratsin. Hozircha soz faqat harflardan iborat deb oling — maxsus belgili qidiruv so'zini xavfsiz qilish Almashtirish chuqur va xavfsiz dinamik regex darsida.

Yechim
js
const vazifalar = [
  "Non olish",
  "Nonvoyga borish",
  "Sut olish",
  "Non va sut",
];

const izla = /non/gi;
function qidirXato(royxat) {
  return royxat.filter((vazifa) => izla.test(vazifa));
}

console.log(qidirXato(vazifalar));
console.log(qidirXato(vazifalar));

function qidir(royxat, soz) {
  const naqsh = new RegExp(soz, "i");
  return royxat.filter((vazifa) => naqsh.test(vazifa));
}

console.log(qidir(vazifalar, "non"));

Konsolda:

text
[ 'Non olish', 'Non va sut' ]
[ 'Nonvoyga borish', 'Non va sut' ]
[ 'Non olish', 'Nonvoyga borish', 'Non va sut' ]

Bir xil chaqiruv — ikki xil natija. Ikkalasi ham noto'g'ri. Birinchi chaqiruv lastIndex ni 3 da qoldirdi, ikkinchisi shu holatdan boshladi. Bunday xato foydalanuvchi uchun "qidiruv ba'zan ishlamaydi" bo'lib ko'rinadi. Tuzatilgan versiyada g yo'q va regex har chaqiruvda yangi.

bash
git add 12/06-qidiruv/qidiruv.mjs
git commit -m "12/06: qidiruvda g flagi va lastIndex tuzog'i"

11. Real ishda

  • Qidiruv va filtrlar. g bilan test — ESLint'da ham, kod tekshiruvida ham tez-tez ushlanadigan xato. Ko'p jamoalarda "test uchun g yo'q" yozilmagan qoida bor.
  • Tahlilchilar (parser). Matnni token'larga bo'luvchi kichik tahlilchilarda y flagi qulay: hech bir belgi jimgina yo'qolmaydi. Formula maydoni, shablon tillari, buyruq qatori argumentlari — shunday joylar.
  • Muharrir va vositalar. d flagi kod muharrirlarida xato joyini belgilash, qidiruv natijalarini bo'yash uchun ishlatiladi.
  • Intervyu. "Nega /a/g.test() ikkinchi marta false qaytaradi?", "m va s farqi?", "y flagi nima uchun?" — lastIndex savoli middle intervyularida ayniqsa ko'p uchraydi.

Xulosa

  • Sakkizta flag: g hammasi, i harf kattaligi, m qatorlar uchun langarlar, s nuqta + yangi qator, u/v Unicode, y aynan shu joydan, d guruh o'rinlari.
  • flags — flaglar satri (doim dgimsuvy tartibida); global, sticky kabi xususiyatlar faqat o'qish uchun.
  • g yoki y bilan test/exec lastIndex dan qidiradi va uni suradi; topmasa — 0.
  • lastIndex regex obyektiga tegishli: bitta regex bilan turli matnlarni tekshirish natijani "sakratadi". test uchun g qo'ymang.
  • y — tushunmagan belgini o'tkazib yubormaydigan, bo'laklab o'qish rejimi; d — indices bilan guruhlar o'rni.
  • (?i:...), (?-i:...) — naqshning bir qismi uchun i, m, s (ES2025).

Keyingi dars: Lookahead va lookbehind — atrofdagi matnni "yemasdan" tekshiramiz: parol talablari va sonlarni minglik bo'yicha ajratish.

Manbalar

  • MDN: "RegExp.prototype.flags", "lastIndex", "sticky", "hasIndices", "dotAll", "Modifier" — developer.mozilla.org
  • ECMAScript 2025 Language Specification, 22.2.6 "Properties of the RegExp Prototype Object" va RegExpBuiltinExec — tc39.es/ecma262
  • TC39 taklifi: "RegExp Modifiers" — github.com/tc39/proposal-regexp-modifiers
  • MDN browser-compat-data 8.1.4 — modifikatorlar va flaglar qo'llanishi
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Regex flaglari: g i m s u v y d va lastIndex tuzog'i — IlmHamroh