6 сентябр 2025

Oldinga va orqaga qarash

Ba’zan bizga faqat boshqa naqsh tomonidan kuzatib borilgan yoki undan oldin kelgan naqsh uchun mosliklarni topish kerak.

Buning uchun “oldinga qarash” va “orqaga qarash” deb ataladigan maxsus sintaksis mavjud, ular birgalikda “atrofga qarash” deb ataladi.

Boshida, 1 turkey costs 30€ kabi satrdan narxni topaylik. Ya’ni: raqam, keyin belgisi.

Oldinga qarash

Sintaksis: X(?=Y), bu “X ni qidir, lekin faqat Y tomonidan kuzatib borilganda mos kel” degani. X va Y o’rniga har qanday naqsh bo’lishi mumkin.

tomonidan kuzatib boriladigan butun son uchun regexp \d+(?=€) bo’ladi:

let str = "1 turkey costs 30€";

alert( str.match(/\d+(?=€)/) ); // 30, 1 raqami e'tiborga olinmaydi, chunki u € bilan kuzatib borilmaydi

E’tibor bering: oldinga qarash shunchaki test, qavslar ichidagi mazmun (?=...) natija 30 ga kiritilmaydi.

X(?=Y) ni qidirganimizda, doimiy ifoda dvigateli X ni topadi, keyin undan keyin darhol Y bormi deb tekshiradi. Agar bo’lmasa, potensial moslik o’tkazib yuboriladi va qidiruv davom etadi.

Murakkabroq testlar ham mumkin, masalan X(?=Y)(?=Z) quyidagini bildiradi:

  1. X ni top.
  2. X dan keyin darhol Y bormi tekshir (bo’lmasa o’tkazib yubor).
  3. X dan keyin darhol Z ham bormi tekshir (bo’lmasa o’tkazib yubor).
  4. Agar ikkala test ham o’tgan bo’lsa, X moslik, aks holda qidirishni davom ettir.

Boshqacha qilib aytganda, bunday naqsh X ni bir vaqtning o’zida Y va Z tomonidan kuzatib boriladigan qidirishni bildiradi.

Bu faqat Y va Z naqshlari bir-birini istisno qilmagan holda mumkin.

Masalan, \d+(?=\s)(?=.*30) bo’shliq (?=\s) tomonidan kuzatib boriladigan va undan keyin biror joyda 30 bor (?=.*30) \d+ ni qidiradi:

let str = "1 turkey costs 30€";

alert( str.match(/\d+(?=\s)(?=.*30)/) ); // 1

Bizning satrda bu aynan 1 raqamiga mos keladi.

Salbiy oldinga qarash

Aytaylik, biz narx emas, balki bir xil satrdan miqdorni xohlaymiz. Bu \d+ raqam, tomonidan kuzatib borilMAYDI.

Buning uchun salbiy oldinga qarashndan foydalanish mumkin.

Sintaksis: X(?!Y), bu “X ni qidir, lekin faqat Y tomonidan kuzatib borilmaganda” degani.

let str = "2 turkeys cost 60€";

alert( str.match(/\d+\b(?!€)/g) ); // 2 (narx mos kelmaydi)

Orqaga qarash

Oldinga qarash “nima keyin keladi” uchun shart qo’shish imkonini beradi.

Orqaga qarash o’xshash, lekin orqaga qaradi. Ya’ni, faqat undan oldin biror narsa bo’lgan holda naqshga mos kelish imkonini beradi.

Sintaksis:

  • Ijobiy orqaga qarash: (?<=Y)X, X ga mos keladi, lekin faqat undan oldin Y bo’lganda.
  • Salbiy orqaga qarash: (?<!Y)X, X ga mos keladi, lekin faqat undan oldin Y bo’lmaganda.

Masalan, narxni AQSh dollariga o’zgartiraylik. Dollar belgisi odatda raqamdan oldin keladi, shuning uchun $30 ni qidirish uchun (?<=\$)\d+ ishlatamiz – $ tomonidan oldin kelgan miqdor:

let str = "1 turkey costs $30";

// dollar belgisi ekranlangan \$
alert( str.match(/(?<=\$)\d+/) ); // 30 (yagona raqam o'tkazib yuborildi)

Va agar bizga miqdor kerak bo’lsa – $ tomonidan oldin kelmaydigan raqam, unda salbiy orqaga qarash (?<!\$)\d+ ishlatishimiz mumkin:

let str = "2 turkeys cost $60";

alert( str.match(/(?<!\$)\b\d+/g) ); // 2 (narx mos kelmaydi)

Ushlash guruhlari

Umuman olganda, atrofga qarash qavslar ichidagi mazmun natijaning bir qismi bo’lmaydi.

Masalan, \d+(?=€) naqshida belgisi moslikning bir qismi sifatida ushlanmaydi. Bu tabiiy: biz \d+ raqamini qidirapmiz, (?=€) esa u tomonidan kuzatib borilishi kerakligi uchun shunchaki test.

Lekin ba’zi hollarda biz atrofga qarash ifodasi yoki uning bir qismini ham ushlashni xohlashimiz mumkin. Bu mumkin. Shu qismni qo’shimcha qavslarga o’rab oling.

Quyidagi misolda valyuta belgisi (€|kr) miqdor bilan birga ushlanadi:

let str = "1 turkey costs 30€";
let regexp = /\d+(?=(€|kr))/; // €|kr atrofida qo'shimcha qavslar

alert( str.match(regexp) ); // 30, €

Va mana orqaga qarash uchun xuddi shunday:

let str = "1 turkey costs $30";
let regexp = /(?<=(\$|£))\d+/;

alert( str.match(regexp) ); // 30, $

Xulosa

Oldinga va orqaga qarash (odatda “atrofga qarash” deb ataladi) undan oldin/keyin kontekstga qarab biror narsaga mos kelishni xohlaganimizda foydali.

Oddiy regexplar uchun biz xuddi shunday narsani qo’lda qilishimiz mumkin. Ya’ni: hamma narsani, istalgan kontekstda moslashtirib, keyin tsiklda kontekst bo’yicha filtrlash.

Eslatib qo’yamiz, str.match (g bayrog’isiz) va str.matchAll (har doim) mosliklarni index xususiyati bilan massivlar sifatida qaytaradi, shuning uchun biz matnda aniq qayerda ekanligini bilamiz va kontekstni tekshira olamiz.

Lekin umuman olganda atrofga qarash qulayroq.

Atrofga qarash turlari:

Naqsh turi mos keladi
X(?=Y) Ijobiy oldinga qarash agar Y tomonidan kuzatib borilsa X
X(?!Y) Salbiy oldinga qarash agar Y tomonidan kuzatib borilmasa X
(?<=Y)X Ijobiy orqaga qarash agar Y dan keyin bo’lsa X
(?<!Y)X Salbiy orqaga qarash agar Y dan keyin bo’lmasa X

Vazifalar

Butun sonlar qatori mavjud.

Faqat salbiy bo’lmaganlarni qidiradigan regexp yarating (nolga ruxsat beriladi).

Foydalanish misoli:

let regexp = /sizning regexp/g;

let str = "0 12 -5 123 -18";

alert(str.match(regexp)); // 0, 12, 123

Butun son uchun regexp \d+ dir.

Biz uning oldiga salbiy orqaga qarashni qo’yish orqali salbiy sonlarni chiqarib tashlashimiz mumkin: (?<!-)\d+.

Biroq, agar biz buni hozir sinab ko’rsak, yana bitta “ortiqcha” natijani payqashimiz mumkin:

let regexp = /(?<!-)\d+/g;

let str = "0 12 -5 123 -18";

console.log( str.match(regexp) ); // 0, 12, 123, 8

Ko’rib turganimizdek, u -18 dan 8 ga mos keladi. Buni chiqarib tashlash uchun regexp sonni boshqa (mos kelmaydigan) sonning o’rtasidan emas, balki boshidan boshlashini ta’minlashimiz kerak.

Buni boshqa salbiy orqaga qarashni belgilash orqali qilishimiz mumkin: (?<!-)(?<!\d)\d+. Endi (?<!\d) moslik boshqa raqamdan keyin boshlanmasligini ta’minlaydi, aynan bizga kerak bo’lgan narsa.

Biz ularni bu yerda bitta orqaga qarashga birlashtirishimiz ham mumkin:

let regexp = /(?<![-\d])\d+/g;

let str = "0 12 -5 123 -18";

alert( str.match(regexp) ); // 0, 12, 123

Bizda HTML hujjati bo’lgan qator mavjud.

<body> tegidan keyin darhol <h1>Salom</h1> qo`shiladigan oddiy iborani yozing. Teg atributlarga ega bo’lishi mumkin.

Masalan:

let regexp = /sizning muntazam ifodangiz/;

let str = `
<html>
  <body style="height: 200px">
  ...
  </body>
</html>
`;

str = str.replace(regexp, `<h1>Salom</h1>`);

Shundan so’ng “str” ​​qiymati quyidagicha bo’lishi kerak:

<html>
  <body style="height: 200px">
    <h1>Salom</h1>
    ...
  </body>
</html>

<body> teg’idan keyin qo’shish uchun avval uni topishimiz kerak. Buning uchun <body.*?> muntazam ifoda naqshidan foydalanishimiz mumkin.

Ushbu vazifada biz <body> teg’ini o’zgartirishimiz shart emas. Faqat undan keyin matn qo’shishimiz kerak.

Buni qanday qilishimiz mumkin:

let str = '...<body style="...">...';
str = str.replace(/<body.*?>/, '$&<h1>Salom</h1>');

alert(str); // ...<body style="..."><h1>Salom</h1>...

Almashtirish satrida $& moslikning o’zini anglatadi, ya’ni <body.*?> ga mos keladigan manba matn qismi. U o’zi va <h1>Salom</h1> bilan almashtiriladi.

Muqobil variant orqaga qarashdan foydalanishdir:

let str = '...<body style="...">...';
str = str.replace(/(?<=<body.*?>)/, `<h1>Salom</h1>`);

alert(str); // ...<body style="..."><h1>Salom</h1>...

Ko’rib turganimizdek, bu regexpda faqat orqaga qarash qismi bor.

U quyidagicha ishlaydi:

  • Matndagi har bir pozitsiyada.
  • U <body.*?> bilan boshlanganini tekshiradi.
  • Agar shunday bo’lsa, bizda moslik bor.

<body.*?> tegi qaytarilmaydi. Ushbu regexp natijasi tom ma’noda bo’sh satrdir, lekin u faqat <body.*?> bilan boshlangan pozitsiyalarda mos keladi.

Shunday qilib, u <body.*?> bilan boshlangan "bo’sh qator"ni <h1>Salom</h1> bilan almashtiradi. Bu <body> dan keyin qo’shishdir.

P.S. s va i kabi regexp bayroqlari ham foydali bo’lishi mumkin: /<body.*?>/si. s bayrog’i nuqta . ni yangi qator belgisiga mos kelishini ta’minlaydi va i bayrog’i <body> ni <BODY> ga ham katta-kichik harflarni farqlamasdan mos kelishini ta’minlaydi.

O'quv qo'llanma xaritasi

Izohlar

izoh berishdan oldin buni o'qing…
  • Agar sizda nimani yaxshilash kerakligi haqida takliflaringiz bo'lsa - iltimos, GitHub muammosini yuboring yoki izoh berish o'rniga so'rov yuboring.
  • Agar siz maqolada biror narsani tushunolmasangiz - iltimos, batafsilroq ma'lumot bering.
  • Bir nechta so'z so'zlarini kiritish uchun <code> yorlig'ini ishlating, bir nechta satrlar uchun - ularni <pre> yorlig'i bilan o'rab qo'ying, 10 satrdan ortiq bo'lsa - sandbox (plnkr, jsbin, codepen…)