6 сентябр 2025

To'plamlar va diapazonlar [...]

Kvadrat qavslar […] ichidagi bir nechta belgilar yoki belgilar sinflari “berilganlar orasidan har qanday belgini qidirish” degani.

To’plamlar

Masalan, [eao] 3 ta belgidan istalgan birini bildiradi: 'a', 'e', yoki 'o'.

Bu to’plam deb ataladi. To’plamlar regexpda oddiy belgilar bilan birga ishlatilishi mumkin:

// [t yoki m], keyin "op" ni topish
alert( "Mop top".match(/[tm]op/gi) ); // "Mop", "top"

E’tibor bering, to’plamda bir nechta belgi bo’lishiga qaramay, ular moslikda aynan bitta belgiga mos keladi.

Shuning uchun quyidagi misol hech qanday moslik bermaydi:

// "V", keyin [o yoki i], keyin "la" ni topish
alert( "Voila".match(/V[oi]la/) ); // null, moslik yo'q

Naqsh quyidagini qidiradi:

  • V,
  • keyin [oi] harflaridan bittasi,
  • keyin la.

Shunday qilib, Vola yoki Vila uchun moslik bo’ladi.

Diapazonlar

Kvadrat qavslar belgilar diapazonlarini ham o’z ichiga olishi mumkin.

Masalan, [a-z] a dan z gacha oraliqdagi belgi, va [0-5] 0 dan 5 gacha raqam.

Quyidagi misolda biz "x" dan keyin ikki raqam yoki A dan F gacha harflarni qidirapmiz:

alert( "Exception 0xAF".match(/x[0-9A-F][0-9A-F]/g) ); // xAF

Bu yerda [0-9A-F] ikki diapazonqa ega: u 0 dan 9 gacha raqam yoki A dan F gacha harf bo’lgan belgini qidiradi.

Agar kichik harflarni ham qidirishni xohlasak, a-f diapazonini qo’shishimiz mumkin: [0-9A-Fa-f]. Yoki i bayrog’ini qo’shish.

Shuningdek, […] ichida belgilar sinflaridan ham foydalanishimiz mumkin.

Masalan, agar so’z belgisi \w yoki tire - ni qidirishni xohlasak, to’plam [\w-] bo’ladi.

Bir nechta sinflarni birlashtirish ham mumkin, masalan [\s\d] “bo’shliq belgisi yoki raqam” degani.

Belgilar sinflari ma’lum belgilar to’plamlari uchun qisqartma

Masalan:

  • \d[0-9] bilan bir xil,
  • \w[a-zA-Z0-9_] bilan bir xil,
  • \s[\t\n\v\f\r ] bilan bir xil, shuningdek bir nechta kam uchraydigan Unicode bo’shliq belgilari.

Misol: ko’p tilli \w

\w belgilar sinfi [a-zA-Z0-9_] uchun qisqartma bo’lgani uchun, u xitoy ierogliflarini, kirill harflarini va hokazolarni topa olmaydi.

Biz har qanday tildagi so’z belgilarini qidiradigan universal naqsh yozishimiz mumkin. Unicode xususiyatlari bilan bu oson: [\p{Alpha}\p{M}\p{Nd}\p{Pc}\p{Join_C}].

Keling, buni yechaylik. \w ga o’xshab, biz quyidagi Unicode xususiyatlariga ega belgilarni o’z ichiga olgan o’z to’plamimizni yaratmoqdamiz:

  • Alphabetic (Alpha) – harflar uchun,
  • Mark (M) – urg’u belgilari uchun,
  • Decimal_Number (Nd) – raqamlar uchun,
  • Connector_Punctuation (Pc) – pastki chiziq '_' va shunga o’xshash belgilar uchun,
  • Join_Control (Join_C) – 200c va 200d ikkita maxsus kod, ligaturalarda ishlatiladi, masalan arab tilida.

Foydalanish misoli:

let regexp = /[\p{Alpha}\p{M}\p{Nd}\p{Pc}\p{Join_C}]/gu;

let str = `Hi 你好 12`;

// barcha harflar va raqamlarni topadi:
alert( str.match(regexp) ); // H,i,你,好,1,2

Albatta, biz bu naqshni tahrirlashimiz mumkin: Unicode xususiyatlarini qo’shish yoki olib tashlash. Unicode xususiyatlari Unicode: "u" bayrog'i va \p{...} sinfi maqolasida batafsil ko’rib chiqilgan.

Unicode xususiyatlari IE da qo’llab-quvvatlanmaydi

Unicode xususiyatlari p{…} IE da amalga oshirilmagan. Agar ular haqiqatan ham kerak bo’lsa, XRegExp kutubxonasidan foydalanishimiz mumkin.

Yoki bizni qiziqtiradigan tildagi belgilar diapazonlarini ishlatish, masalan kirill harflari uchun [а-я].

Istisno diapazonlar

Oddiy diapazonlardan tashqari, [^…] ko’rinishidagi “istisno” diapazonlar ham mavjud.

Ular boshida karet belgisi ^ bilan belgilanadi va berilganlardan tashqari har qanday belgiga mos keladi.

Masalan:

  • [^aeyo]'a', 'e', 'y' yoki 'o' dan tashqari har qanday belgi.
  • [^0-9] – raqamdan tashqari har qanday belgi, \D bilan bir xil.
  • [^\s] – bo’shliq bo’lmagan har qanday belgi, \S bilan bir xil.

Quyidagi misol harflar, raqamlar va bo’shliqlardan tashqari har qanday belgilarni qidiradi:

alert( "alice15@gmail.com".match(/[^\d\sA-Z]/gi) ); // @ va .

[…] da ekranlash

Odatda maxsus belgini aniq topishni xohlaganimizda, uni \. kabi ekranlashimiz kerak. Va agar teskari chiziq kerak bo’lsa, \\ ishlatamiz va hokazo.

Kvadrat qavslarda biz ko’pgina maxsus belgilarni ekranlamay ishlatishimiz mumkin:

  • . + ( ) belgilari hech qachon ekranlanmaydi.
  • Tire - boshida yoki oxirida ekranlanmaydi (bu yerda u diapazon belgilamaydi).
  • Karet ^ faqat boshida ekranlanadi (bu yerda u istisno bildiradi).
  • Yopuvchi kvadrat qavs ] har doim ekranlanadi (agar shu belgini qidirishimiz kerak bo’lsa).

Boshqacha qilib aytganda, kvadrat qavslar uchun biror ma’no bildirmagan holda, barcha maxsus belgilarga ruxsat beriladi.

Kvadrat qavslar ichidagi nuqta . shunchaki nuqta degani. [.,] naqshi belgilardan birini qidiradi: nuqta yoki vergul.

Quyidagi misolda [-().^+] regexp -().^+ belgilaridan birini qidiradi:

// Ekranlash kerak emas
let regexp = /[-().^+]/g;

alert( "1 + 2 - 3".match(regexp) ); // +, - ni topadi

…Lekin agar siz ularni “har holda” ekranlashga qaror qilsangiz, hech qanday zarar bo’lmaydi:

// Hamma narsani ekranlash
let regexp = /[\-\(\)\.\^\+]/g;

alert( "1 + 2 - 3".match(regexp) ); // ham ishlaydi: +, -

Diapazonlar va “u” bayrog’i

Agar to’plamda surrogate juftliklar bo’lsa, ularning to’g’ri ishlashi uchun u bayrog’i kerak.

Masalan, 𝒳 satrida [𝒳𝒴] ni qidiraylik:

alert( '𝒳'.match(/[𝒳𝒴]/) ); // g'alati belgi ko'rsatadi, [?] kabi
// (qidiruv noto'g'ri amalga oshirildi, yarim belgi qaytarildi)

Natija noto’g’ri, chunki sukut bo’yicha doimiy ifodalar surrogate juftliklar haqida “bilmaydi”.

Doimiy ifoda dvigateli [𝒳𝒴] – ikkita emas, balki to’rtta belgi deb o’ylaydi:

  1. 𝒳 ning chap yarmi (1),
  2. 𝒳 ning o’ng yarmi (2),
  3. 𝒴 ning chap yarmi (3),
  4. 𝒴 ning o’ng yarmi (4).

Ularning kodlarini quyidagicha ko’rishimiz mumkin:

for(let i=0; i<'𝒳𝒴'.length; i++) {
  alert('𝒳𝒴'.charCodeAt(i)); // 55349, 56499, 55349, 56500
};

Shunday qilib, yuqoridagi misol 𝒳 ning chap yarmini topadi va ko’rsatadi.

Agar biz u bayrog’ini qo’shsak, harakat to’g’ri bo’ladi:

alert( '𝒳'.match(/[𝒳𝒴]/u) ); // 𝒳

[𝒳-𝒴] kabi diapazonni qidirishda ham xuddi shunday vaziyat yuz beradi.

Agar biz u bayrog’ini qo’shishni unutsak, xato bo’ladi:

'𝒳'.match(/[𝒳-𝒴]/); // Xato: Invalid regular expression

Sababi shundaki, u bayrog’isiz surrogate juftliklar ikkita belgi sifatida qabul qilinadi, shuning uchun [𝒳-𝒴] [<55349><56499>-<55349><56500>] sifatida talqin qilinadi (har bir surrogate juftlik o’z kodlari bilan almashtiriladi). Endi 56499-55349 diapazonining noto’g’ri ekanligini osongina ko’rish mumkin: boshlang’ich kodi 56499 oxirgi 55349dan katta. Bu xatoning rasmiy sababi.

u bayrog’i bilan naqsh to’g’ri ishlaydi:

// 𝒳 dan 𝒵 gacha belgilarni qidirish
alert( '𝒴'.match(/[𝒳-𝒵]/u) ); // 𝒴

Vazifalar

Bizda regex /Javascript]/ mavjud.

U Java qatoridagi biror narsaga mos keladimi? JavaScript qatorida?

Javoblar: no, yes.

  • Java skriptida u hech narsaga mos kelmaydi, chunki [^script] “berilganlardan tashqari har qanday belgi” degan ma’noni anglatadi. Shunday qilib, regexp "Java" dan keyin bitta shunday belgini qidiradi, lekin satr oxiri bor, undan keyin hech qanday belgi yo’q.

    alert("Java".match(/Java[^script]/)); // null
  • Ha, chunki [^script] qismi "S" belgisiga mos keladi. Bu “pattern:script” dan biri emas. Regexp katta-kichik harflarga sezgir bo’lgani uchun ("pattern:i" bayrog’i yo’q), u "S" ni "s" dan boshqa belgi sifatida ko’radi.

    alert("JavaScript".match(/Java[^script]/)); // "JavaS"

Vaqt soat: daqiqa yoki soat-daqiqa formatida bo’lishi mumkin. Har ikkala soat va daqiqada 2 ta raqam mavjud: 09:00 yoki 21-30.

Vaqtni topish uchun regexp yozing:

let regexp = /your regexp/g;
alert("Breakfast at 09:00. Dinner at 21-30".match(regexp)); // 09:00, 21-30

P.S. Ushbu vazifada biz vaqt har doim to’g’ri deb hisoblaymiz, “45:67” kabi yomon satrlarni filtrlashning hojati yo’q. Keyinchalik bu bilan ham shug’ullanamiz.

Javob: \d\d[-:]\d\d.

let regexp = /\d\d[-:]\d\d/g;
alert("Breakfast at 09:00. Dinner at 21-30".match(regexp)); // 09:00, 21-30

Esda tutingki, '-' tire kvadrat qavs ichida alohida ma’noga ega, lekin faqat boshqa belgilar orasida, u boshida yoki oxirida bo’lganda emas, shuning uchun biz undan qochishimiz shart emas.

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…)