[ Web Proxy ]
URL:
Viewing: https://uz.javascript.info/regexp-groups [Back]  [Original]

Ushlash guruhlari
UZ

Ushbu ochiq manbali loyihani butun dunyo bo'ylab odamlar uchun taqdim etmoqchimiz.

Ushbu qo'llanmaning mazmuni sizning tilingizga tarjima qilishga yordam bering!

    Javascript.info saytidan qidirish:
    O'quv qo'llanmasidan qidiring:
    Light themeDark theme
    DanskEnglishEspaolFranaisIndonesiaItalianoTrkeOzbek

    Ushlash guruhlari

    Naqshning bir qismi qavslar (...) ichiga olinishi mumkin. Bu ushlash guruhi deb ataladi.

    Buning ikkita tasiri bor:

    1. Moslikning bir qismini natijalar massivida alohida element sifatida olish imkonini beradi.
    2. Agar qavslardan keyin miqdorchi qoysak, u butun qavslar guruhi uchun qollaniladi.

    Misollar

    Qavslar qanday ishlashini misollarda koraylik.

    Misol: gogogo

    Qavslarsiz go+ naqshi g belgisini, keyin bir yoki kop marta takrorlangan o ni bildiradi. Masalan, goooo yoki gooooooooo.

    Qavslar belgilarni birlashtirib guruhlaydi, shuning uchun (go)+ go, gogo, gogogo va hokazolarni bildiradi.

    alert( 'Gogogo now!'.match(/(go)+/ig) ); // "Gogogo"

    Misol: domen

    Keling, murakkabroq narsa yasaylik veb-sayt domenini qidiruvchi doimiy ifoda.

    Masalan:

    mail.com
    users.mail.com
    smith.users.mail.com

    Korib turganingizdek, domen takrorlanuvchi sozlardan iborat, oxirgisidan tashqari har biridan keyin nuqta.

    Doimiy ifodalarda bu (\w+\.)+\w+:

    let regexp = /(\w+\.)+\w+/g;
    
    alert( "site.com my.site.com".match(regexp) ); // site.com,my.site.com

    Qidiruv ishlaydi, lekin naqsh tire bilan domenga mos kelmaydi, masalan my-site.com, chunki tire \w sinfiga tegishli emas.

    Buni oxirgisidan tashqari har bir sozda \w ni [\w-] bilan almashtirish orqali tuzatishimiz mumkin: ([\w-]+\.)+\w+.

    Misol: email

    Oldingi misolni kengaytirish mumkin. Unga asoslanib emaillar uchun doimiy ifoda yaratishimiz mumkin.

    Email formati: name@domain. Har qanday soz nom bolishi mumkin, tireler va nuqtalar ruxsat etiladi. Doimiy ifodalarda bu [-.\w]+.

    Naqsh:

    let regexp = /[-.\w]+@([\w-]+\.)+[\w-]+/g;
    
    alert("my@mail.com @ his@site.com.uk".match(regexp)); // my@mail.com, his@site.com.uk

    Bu regexp mukammal emas, lekin asosan ishlaydi va tasodifiy xatolarni tuzatishga yordam beradi. Email uchun yagona ishonchli tekshiruv faqat xat yuborish orqali amalga oshirilishi mumkin.

    Mosliklarda qavslar mazmuni

    Qavslar chapdan ongga raqamlanadi. Qidiruv dvigateli ularning har bir mos kelgan mazmunni eslab qoladi va natijada olish imkonini beradi.

    str.match(regexp) metodi, agar regexpda g bayrogi bolmasa, birinchi moslikni qidiradi va uni massiv korinishida qaytaradi:

    1. 0 indeksida: toliq moslik.
    2. 1 indeksida: birinchi qavslar mazmuni.
    3. 2 indeksida: ikkinchi qavslar mazmuni.
    4. va hokazo

    Masalan, biz HTML teglarini <.*?> topmoqchimiz va ularni qayta ishlamoqchimiz. Teg mazmuni (burchaklar ichidagi narsa)ni alohida ozgaruvchida bolishi qulay bolardi.

    Ichki mazmunni qavslarga oraylik: <(.*?)>.

    Endi biz natijalar massivida ham butun teg <h1> ham uning mazmuni h1 ni olamiz:

    let str = '<h1>Hello, world!</h1>';
    
    let tag = str.match(/<(.*?)>/);
    
    alert( tag[0] ); // <h1>
    alert( tag[1] ); // h1

    Ichki guruhlar

    Qavslar ichma-ich bolishi mumkin. Bu holda raqamlash ham chapdan ongga boradi.

    Masalan, <span class="my"> da tegni qidirishda bizni qiziqtirishi mumkin:

    1. Butun teg mazmuni: span class="my".
    2. Teg nomi: span.
    3. Teg atributlari: class="my".

    Ular uchun qavslar qoshaylik: <(([a-z]+)\s*([^>]*))>.

    Ular qanday raqamlanishi (chapdan ongga, ochuvchi qavs boyicha):

    []

    Amalda:

    let str = '<span class="my">';
    
    let regexp = /<(([a-z]+)\s*([^>]*))>/;
    
    let result = str.match(regexp);
    alert(result[0]); // <span class="my">
    alert(result[1]); // span class="my"
    alert(result[2]); // span
    alert(result[3]); // class="my"

    result ning nol indeksi har doim toliq moslikni saqlaydi.

    Keyin chapdan ongga ochuvchi qavs boyicha raqamlangan guruhlar. Birinchi guruh result[1] sifatida qaytariladi. Bu yerda u butun teg mazmunini orab oladi.

    Keyin result[2] da ikkinchi ochuvchi qavs ([a-z]+) dan guruh teg nomi, keyin result[3] da teg: ([^>]*).

    Satrdagi har bir guruh mazmuni:

    []

    Ixtiyoriy guruhlar

    Agar guruh ixtiyoriy bolsa va moslikda mavjud bolmasa (masalan, (...)? miqdorchisiga ega), tegishli result massiv elementi mavjud va undefined ga teng.

    Masalan, a(z)?(c)? regexpni korib chiqaylik. U "a" ni, ixtiyoriy ravishda "z" keyin, ixtiyoriy ravishda "c" keyin qidiradi.

    Agar uni bitta harf a bilan satrda ishga tushirsak, natija:

    let match = 'a'.match(/a(z)?(c)?/);
    
    alert( match.length ); // 3
    alert( match[0] ); // a (to'liq moslik)
    alert( match[1] ); // undefined
    alert( match[2] ); // undefined

    Massiv uzunligi 3, lekin barcha guruhlar bosh.

    Va ac satr uchun murakkabroq moslik:

    let match = 'ac'.match(/a(z)?(c)?/)
    
    alert( match.length ); // 3
    alert( match[0] ); // ac (to'liq moslik)
    alert( match[1] ); // undefined, chunki (z)? uchun hech narsa yo'q
    alert( match[2] ); // c

    Massiv uzunligi doimiy: 3. Lekin (z)? guruhi uchun hech narsa yoq, shuning uchun natija ["ac", undefined, "c"].

    Guruhlar bilan barcha mosliklarni qidirish: matchAll

    matchAll yangi metod, polyfill kerak bolishi mumkin

    matchAll metodi eski brauzerlarda qollab-quvvatlanmaydi.

    Polyfill kerak bolishi mumkin, masalan https://github.com/ljharb/String.prototype.matchAll.

    Barcha mosliklarni qidirishda (g bayrogi), match metodi guruhlar uchun mazmunni qaytarmaydi.

    Masalan, satrdagi barcha teglarni topaylik:

    let str = '<h1> <h2>';
    
    let tags = str.match(/<(.*?)>/g);
    
    alert( tags ); // <h1>,<h2>

    Natija mosliklar massivi, lekin ularning har biri haqida tafsilot yoq. Lekin amalda biz odatda natijada ushlash guruhlarining mazmuniga muhtojmiz.

    Ularni olish uchun str.matchAll(regexp) metodidan foydalanishimiz kerak.

    U JavaScript tiliga matchdan ancha keyin, uning yangi va yaxshilangan versiyasi sifatida qoshildi.

    match kabi u mosliklarni qidiradi, lekin 3 ta farq bor:

    1. U massiv emas, balki iteratsiya qilinadigan obyekt qaytaradi.
    2. g bayrogi mavjud bolganda, u har bir moslikni guruhlar bilan massiv sifatida qaytaradi.
    3. Agar moslik bolmasa, null emas, balki bosh iteratsiya qilinadigan obyekt qaytaradi.

    Masalan:

    let results = '<h1> <h2>'.matchAll(/<(.*?)>/gi);
    
    // results - massiv emas, balki iteratsiya qilinadigan obyekt
    alert(results); // [object RegExp String Iterator]
    
    alert(results[0]); // undefined (*)
    
    results = Array.from(results); // uni massivga aylantiraylik
    
    alert(results[0]); // <h1>,h1 (1-teg)
    alert(results[1]); // <h2>,h2 (2-teg)

    Korib turganingizdek, birinchi farq juda muhim, (*) satrida korsatilganidek. Biz moslikni results[0] sifatida ola olmaymiz, chunki bu obyekt psevdo-massiv emas. Uni Array.from yordamida haqiqiy Array ga aylantirish mumkin. Psevdo-massivlar va iteratsiya qilinadigan obyektlar haqida koproq malumot Tsiklda korib chiqish imokniyatiga ega malumot turlari maqolasida.

    Agar natijalarni aylantirayotgan bolsak, Array.from ga ehtiyoj yoq:

    let results = '<h1> <h2>'.matchAll(/<(.*?)>/gi);
    
    for(let result of results) {
      alert(result);
      // birinchi alert: <h1>,h1
      // ikkinchi: <h2>,h2
    }

    Yoki destrukturizatsiya yordamida:

    let [tag1, tag2] = '<h1> <h2>'.matchAll(/<(.*?)>/gi);

    matchAll tomonidan qaytarilgan har bir moslik g bayrogisiz match tomonidan qaytarilgan format bilan bir xil: bu qoshimcha index (satrdagi moslik indeksi) va input (manba satr) xususiyatlari bilan massiv:

    let results = '<h1> <h2>'.matchAll(/<(.*?)>/gi);
    
    let [tag1, tag2] = results;
    
    alert( tag1[0] ); // <h1>
    alert( tag1[1] ); // h1
    alert( tag1.index ); // 0
    alert( tag1.input ); // <h1> <h2>
    Nima uchun matchAll natijasi massiv emas, balki iteratsiya qilinadigan obyekt?

    Metod nima uchun shunday yaratilgan? Sabab oddiy optimallashtirish uchun.

    matchAll ga chaqiruv qidiruvni amalga oshirmaydi. Buning orniga u dastlab natijalarsiz iteratsiya qilinadigan obyekt qaytaradi. Qidiruv har safar ustidan iteratsiya qilganimizda amalga oshiriladi, masalan tsiklda.

    Shunday qilib, kerak bolgandan kop emas, balki kerak bolganicha natijalar topiladi.

    Masalan, matnda potensial 100 ta moslik bor, lekin for..of tsiklida ulardan 5 tasini topdik, keyin bu yetarli deb qaror qilib break qildik. Keyin dvigatel qolgan 95 ta moslikni topishga vaqt sarflamaydi.

    Nomlangan guruhlar

    Guruhlarni raqamlari boyicha eslash qiyin. Oddiy naqshlar uchun bu mumkin, lekin murakkabroqlari uchun qavslarni sanash noqulay. Bizda ancha yaxshi variant bor: qavslarga nom berish.

    Bu ochuvchi qavsdan keyin darhol ?<name> qoyish orqali amalga oshiriladi.

    Masalan, yil-oy-kun formatida sanani qidiraylik:

    let dateRegexp = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/;
    let str = "2019-04-30";
    
    let groups = str.match(dateRegexp).groups;
    
    alert(groups.year); // 2019
    alert(groups.month); // 04
    alert(groups.day); // 30

    Korib turganingizdek, guruhlar moslikning .groups xususiyatida joylashgan.

    Barcha sanalarni qidirish uchun g bayrogini qoshishimiz mumkin.

    Shuningdek, guruhlar bilan birga toliq mosliklarni olish uchun matchAll kerak boladi:

    let dateRegexp = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/g;
    
    let str = "2019-10-30 2020-01-01";
    
    let results = str.matchAll(dateRegexp);
    
    for(let result of results) {
      let {year, month, day} = result.groups;
    
      alert(`${day}.${month}.${year}`);
      // birinchi alert: 30.10.2019
      // ikkinchi: 01.01.2020
    }

    Almashtirishda ushlash guruhlari

    str dagi regexp bilan barcha mosliklarni replacement bilan almashtiradigan str.replace(regexp, replacement) metodi replacement satrida qavslar mazmunidan foydalanish imkonini beradi. Bu $n yordamida amalga oshiriladi, bu yerda n guruh raqami.

    Masalan,

    let str = "John Bull";
    let regexp = /(\w+) (\w+)/;
    
    alert( str.replace(regexp, '$2, $1') ); // Bull, John

    Nomlangan qavslar uchun havola $<name> boladi.

    Masalan, sanalarni "yil-oy-kun"dan "kun.oy.yil"ga qayta formatlaylik:

    let regexp = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/g;
    
    let str = "2019-10-30, 2020-01-01";
    
    alert( str.replace(regexp, '$<day>.$<month>.$<year>') );
    // 30.10.2019, 01.01.2020

    ?: bilan ushlamaydigan guruhlar

    Bazan miqdorchini togri qollash uchun qavslar kerak, lekin natijalarda ularning mazmuni kerak emas.

    Guruhni boshiga ?: qoshish orqali chiqarib tashlash mumkin.

    Masalan, agar biz (go)+ ni topmoqchi bolsak, lekin qavslar mazmuni (go) ni massivning alohida elementi sifatida istamak, yoza olamiz: (?:go)+.

    Quyidagi misolda biz faqat John nomini moslikning alohida azosi sifatida olamiz:

    let str = "Gogogo John!";
    
    // ?: 'go' ni ushlashdan chiqarib tashlaydi
    let regexp = /(?:go)+ (\w+)/i;
    
    let result = str.match(regexp);
    
    alert( result[0] ); // Gogogo John (to'liq moslik)
    alert( result[1] ); // John
    alert( result.length ); // 2 (massivda boshqa elementlar yo'q)

    Xulosa

    Qavslar doimiy ifodaning bir qismini birlashtirib guruhlaydi, shunda miqdorchi unga butunlay qollaniladi.

    Qavslar guruhlari chapdan ongga raqamlanadi va ixtiyoriy ravishda (?<name>...) bilan nomlanishi mumkin.

    Guruh tomonidan moslashtirilgan mazmunni natijalarda olish mumkin:

    • str.match metodi faqat g bayrogisiz ushlash guruhlarini qaytaradi.
    • str.matchAll metodi har doim ushlash guruhlarini qaytaradi.

    Agar qavslarning nomi bolmasa, ularning mazmuni moslik massivida raqami boyicha mavjud. Nomlangan qavslar groups xususiyatida ham mavjud.

    Shuningdek, str.replace da almashtirish satrida qavslar mazmunidan foydalanishimiz mumkin: raqam $n yoki nom $<name> boyicha.

    Guruhni boshiga ?: qoshish orqali raqamlashdan chiqarib tashlash mumkin. Bu butun guruhga miqdorchi qollashimiz kerak bolganda, lekin uni natijalar massivida alohida element sifatida istamaganimizda ishlatiladi. Shuningdek, bunday qavslarni almashtirish satrida ham ishlatib bolmaydi.

    Vazifalar

    Tarmoq interfeysining Mac-manzili ikkita nuqta bilan ajratilgan 6 ta ikki xonali olti burchakli raqamlardan iborat.

    Masalan: '01:32:54:67:89:AB'.

    Satr MAC-manzil ekanligini tekshiradigan regexp yozing.

    Foydalanish:

    let regexp = /your regexp/;
    
    alert(regexp.test("01:32:54:67:89:AB")); // true
    
    alert(regexp.test("0132546789AB")); // false (ikki nuqta yo'q)
    
    alert(regexp.test("01:32:54:67:89")); // false (5 ta raqam, 6 ta kerak)
    
    alert(regexp.test("01:32:54:67:89:ZZ")); // false (ZZ oxirida)
    yechim

    Ikki xonali olti burchakli raqam [0-9a-f]{2} (i bayroqchasi ornatilgan bolsa).

    Bizga bu raqam NN kerak, keyin esa 5 marta takrorlangan :NN (ko`proq raqamlar);

    Regexp: [0-9a-f]{2}(:[0-9a-f]{2}){5}

    Keling, oyin barcha matnni qamrab olishi kerakligini korsatamiz: boshidan boshlanadi va oxirida tugaydi. Bu naqshni ^...$ ga orash orqali amalga oshiriladi.

    Nihoyat:

    let regexp = /^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}$/i;
    
    alert(regexp.test("01:32:54:67:89:AB")); // true
    
    alert(regexp.test("0132546789AB")); // false (ikki nuqta yo'q)
    
    alert(regexp.test("01:32:54:67:89")); // false (5 ta raqam, 6 ta kerak)
    
    alert(regexp.test("01:32:54:67:89:ZZ")); // false (ZZ oxirida)

    #abc yoki #abcdef formatida ranglarga mos keladigan RegExp yozing. Yani: # keyin 3 yoki 6 on oltilik raqam.

    Masalan:

    let regexp = /sizning regepxiyingiz/g;
    
    let str = "color: #3f3; background-color: #AA00ef; and: #abcd";
    
    alert(str.match(regexp)); // #3f3 #AA00ef

    P.S. Bu aniq 3 yoki 6 hex raqam bolishi kerak. #abcd kabi 4 ta raqamdan iborat qiymatlar mos kelmasligi kerak.

    yechim

    3 xonali #abc rangini qidirish uchun regexp: /#[a-f0-9]{3}/i.

    Biz yana 3 ta ixtiyoriy olti burchakli raqamni qoshishimiz mumkin. Bizga koproq yoki kamroq kerak emas. Rangda 3 yoki 6 ta raqam mavjud.

    Buning uchun {1,2} kvantatoridan foydalanamiz: bizda /#([a-f0-9]{3}){1,2}/i boladi.

    Bu yerda [a-f0-9]{3} namunasi {1,2} kvantini qollash uchun qavslar ichiga olingan.

    Amalda:

    let regexp = /#([a-f0-9]{3}){1,2}/gi;
    
    let str = "color: #3f3; background-color: #AA00ef; and: #abcd";
    
    alert(str.match(regexp)); // #3f3 #AA00ef #abc

    Bu yerda kichik muammo bor: naqsh mavzu:#abcd da #abc topildi. Buning oldini olish uchun oxiriga \b qoshishimiz mumkin:

    let regexp = /#([a-f0-9]{3}){1,2}\b/gi;
    
    let str = "color: #3f3; background-color: #AA00ef; and: #abcd";
    
    alert(str.match(regexp)); // #3f3 #AA00ef

    Barcha onlik sonlarni, shu jumladan butun sonlarni, suzuvchi nuqta va manfiylarni qidiradigan regexp yozing.

    Masalan:

    let regexp = /your regexp/g;
    
    let str = "-1.5 0 2 -123.4.";
    
    alert(str.match(regexp)); // -1.5, 0, 2, -123.4
    yechim

    Ixtiyoriy kasrli musbat son: \d+(\.\d+)?.

    Boshiga ixtiyoriy - qoshamiz:

    let regexp = /-?\d+(\.\d+)?/g;
    
    let str = "-1.5 0 2 -123.4.";
    
    alert(str.match(regexp)); // -1.5, 0, 2, -123.4

    Arifmetik ifoda 2 ta raqam va ular orasidagi operatordan iborat, masalan:

    • 1 + 2
    • 1.2 * 3.4
    • -3 / -6
    • -2 - 2

    Operator quyidagilardan biri: "+", "-", "*" yoki "/".

    Boshida, oxirida yoki qismlar ortasida qoshimcha boshliqlar bolishi mumkin.

    Ifodani qabul qiluvchi va 3 ta elementdan iborat massivni qaytaruvchi parse(expr) funksiyasini yarating:

    1. Birinchi raqam.
    2. Operator.
    3. Ikkinchi raqam.

    Masalan:

    let [a, op, b] = parse("1.2 * 3.4");
    
    alert(a); // 1.2
    alert(op); // *
    alert(b); // 3.4
    yechim
    Arifmetik ifoda tahlilchisi

    Arifmetik ifoda tahlilchisi

    Raqam uchun regexp: -?\d+(\.\d+)?. Buni oldingi vazifada yaratgan edik.

    Operator [-+*/]. Tire - kvadrat qavslarda birinchi orinda turadi, chunki ortada bolsa belgilar diapazonini bildiradi, biz esa shunchaki - belgisini xohlaymiz.

    Qiyshiq chiziq / JavaScript regexp /.../ ichida ekranlanishi kerak, buni keyinroq qilamiz.

    Bizga raqam, operator, keyin yana raqam kerak. Va ular orasida ixtiyoriy boshliqlar.

    Toliq doimiy ifoda: -?\d+(\.\d+)?\s*[-+*/]\s*-?\d+(\.\d+)?.

    Unda \s* bilan ajratilgan 3 ta qism bor:

    1. -?\d+(\.\d+)? birinchi raqam,
    2. [-+*/] operator,
    3. -?\d+(\.\d+)? ikkinchi raqam.

    Bu qismlarning har birini natijalar massivining alohida elementi qilish uchun ularni qavslarga oraylik: (-?\d+(\.\d+)?)\s*([-+*/])\s*(-?\d+(\.\d+)?).

    Amalda:

    let regexp = /(-?\d+(\.\d+)?)\s*([-+*\/])\s*(-?\d+(\.\d+)?)/;
    
    alert("1.2 + 12".match(regexp));

    Natija quyidagilarni oz ichiga oladi:

    • result[0] == "1.2 + 12" (toliq moslik)
    • result[1] == "1.2" (birinchi guruh (-?\d+(\.\d+)?) birinchi raqam, onli qism bilan birga)
    • result[2] == ".2" (ikkinchi guruh (\.\d+)? birinchi onli qism)
    • result[3] == "+" (uchinchi guruh ([-+*\/]) operator)
    • result[4] == "12" (tortinchi guruh (-?\d+(\.\d+)?) ikkinchi raqam)
    • result[5] == undefined (beshinchi guruh (\.\d+)? oxirgi onli qism yoq, shuning uchun undefined)

    Bizga faqat raqamlar va operator kerak, toliq moslik yoki onli qismlar emas, shuning uchun natijani biroz tozalaylik.

    Toliq moslikni (massivning birinchi elementi) massivni siljitish result.shift() orqali olib tashlash mumkin.

    Onli qismlarni oz ichiga olgan guruhlar (2 va 4 raqamli) (.\d+) ni boshiga ?: qoshish orqali chiqarib tashlash mumkin: (?:\.\d+)?.

    Yakuniy yechim:

    function parse(expr) {
      let regexp = /(-?\d+(?:\.\d+)?)\s*([-+*\/])\s*(-?\d+(?:\.\d+)?)/;
    
      let result = expr.match(regexp);
    
      if (!result) return [];
      result.shift();
    
      return result;
    }
    
    alert(parse("-1.23 * 3.45")); // -1.23, *, 3.45
    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)

    Web Proxy Viewer  |  New URL  |  Original Page