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:
X
ni top.X
dan keyin darholY
bormi tekshir (bo’lmasa o’tkazib yubor).X
dan keyin darholZ
ham bormi tekshir (bo’lmasa o’tkazib yubor).- 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 oldinY
bo’lganda. - Salbiy orqaga qarash:
(?<!Y)X
,X
ga mos keladi, lekin faqat undan oldinY
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 |
Izohlar
<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…)