Murakkab regex: lookahead, lookbehind va nomlangan guruhlar
Chuqur3 daqInnovialabs tahririyati
Qisqacha
Lookaround kontekstni ushlamasdan tekshiradi, nomlangan guruhlar mosliklarni o‘qiladigan qiladi, (a+)+ kabi ichma-ich kvantifikatorlar esa halokatli backtracking va ReDoS’ning asosiy manbai.
Murakkab konstruksiyalar nima beradi
Oddiy regex «bunday matn bormi» degan savolga javob beradi. Murakkab konstruksiyalar aniqroq aytishga imkon beradi:
- lookaround — «moslik nimadirning oldida yoki ortida turishi kerak», lekin o‘sha «nimadir» natijaga kirmaydi;
- nomlangan guruhlar — moslik qismlarini raqam bo‘yicha emas, nom bo‘yicha olamiz;
- ushlamaydigan guruhlar — ortiqcha ushlashlarsiz guruhlaymiz;
- dangasa kvantifikatorlar — maksimum o‘rniga minimumni olamiz;
- orqa havolalar — allaqachon topilgan matn takrorlanishini talab qilamiz.
Lookahead va lookbehind
Bular nol kenglikdagi tekshiruvlar: ular qo‘shni matnga qaraydi, lekin uni «yemaydi».
| Konstruksiya | Ma’nosi |
|---|---|
(?=X) | keyin X keladi |
(?!X) | keyin X kelmaydi |
(?<=X) | oldida X turadi |
(?<!X) | oldida X turmaydi |
Klassik misol — sonning xonalarini bo‘sh joy bilan ajratish:
"1234567".replace(/\B(?=(\d{3})+(?!\d))/g, " "); // "1 234 567"
Pozitsiya mos keladi, agar undan keyin son oxirigacha aynan uchtadan raqamli guruhlar kelsa. Raqamlarning o‘zi ushlanmaydi, shuning uchun almashtirish hech narsani o‘chirmasdan bo‘sh joy qo‘shadi.
Ketma-ket bir nechta lookahead shartlarni istalgan tartibda tekshirish uchun qulay: ^(?=.*\d)(?=.*[a-z]).{8,}$ — kamida 8 belgi, raqam va kichik harf bor.
Lookbehind markerdan keyingi qiymatni ajratib oladi: (?<=\$)\d+ $25 ichidan 25 ni topadi. Muhim farq: Python’dagi re moduli qat’iy uzunlikdagi lookbehind talab qiladi, zamonaviy JavaScript dvigatellarida esa uzunlik o‘zgaruvchan bo‘lishi mumkin.
Nomlangan va ushlamaydigan guruhlar
Sintaksis tillar orasida farq qiladi:
const m = "2026-10-19".match(/(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})/);
m.groups.y; // "2026"
"2026-10-19".replace(/(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})/, "$<d>.$<m>.$<y>");
import re
re.sub(r"(?P<y>\d{4})-(?P<m>\d{2})-(?P<d>\d{2})", r"\g<d>.\g<m>.\g<y>", "2026-10-19")
Agar guruh faqat | yoki kvantifikator uchun kerak bo‘lsa, uni ushlamaydigan qiling: (?:https?|ftp)://. Boshqa guruhlarning raqamlari siljimaydi, dvigatelga esa ish kamroq.
Ochko‘z va dangasa kvantifikatorlar
Sukut bo‘yicha *, +, {n,} ochko‘z — iloji boricha ko‘p oladi. <b>x</b> satrida <.+> butun satrni ushlaydi, dangasa <.+?> esa faqat <b> ni.
Ko‘pincha dangasalik o‘rniga ruxsat etilgan belgilarni aniq tasvirlash yaxshiroq: <[^>]+>. Bu ham tushunarliroq, ham tezroq, chunki dvigatel orqaga qaytishi shart emas.
Orqa havolalar
Orqa havola matn takrorlanishini talab qiladi: \b(\w+)\s+\1\b «the the» kabi takrorlangan so‘zni topadi. Nomlangan guruhlar uchun: JavaScript’da \k<word>, Python’da (?P=word).
Halokatli backtracking va ReDoS
JavaScript, Python, Java va boshqa ko‘plab tillarning dvigatellari backtracking orqali ishlaydi: muvaffaqiyatsizlikda kirishni bo‘lishning boshqa variantlarini sinab ko‘radi. ^(a+)+$ ifodasi oxirida ! bo‘lgan uzun a satrida eksponensial sondagi variantlarni sinaydi va jarayonni «qotirib» qo‘yadi. Agar bunday ifoda foydalanuvchi kiritgan ma’lumotni tekshirsa, bu ReDoS — bitta satr bilan xizmatni ishdan chiqarish.
Qanday himoyalanish mumkin:
- bir xil matn ustidagi ichma-ich kvantifikatorlardan qoching:
(a+)+,(\w*)*,(.*,)*; - bir-biriga kesishadigan alternativalardan qoching:
(a|a)*,(\d|\d\d)+; - regex’ni ishga tushirishdan oldin kirish uzunligini cheklang;
- mavjud bo‘lsa, atomar guruhlar
(?>...)va egalovchi kvantifikatorlara++dan foydalaning — ular orqaga qaytishni taqiqlaydi (Python’ning yangi versiyalarida ularrega qo‘shilgan); - ishonchsiz shablonlar yoki kirish uchun RE2 kabi backtracking’siz dvigatellarni oling.
Keng tarqalgan xatolar
- JavaScript’da barcha moslikni almashtirishda
gbayrog‘ini unutish. - Validatsiyada
^va$langarlarining yo‘qligi — tekshiruv satr bo‘lagi bo‘yicha o‘tib ketadi. - Python’da raw-satr
r"..."o‘rniga oddiy satr, natijada\bbackspace’ga aylanadi. - Parser yoki ikkita oddiy tekshiruv osonroq bo‘lgan joyda bitta ulkan regex.