Mundarija (23)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Muntazam ifoda nima
- 2.2. Beshta asosiy funksiya
- 2.3. Nega r"..." majburiy
- 2.4. Ekranlash
- 2.5. Belgilar sinflari
- 2.6. Miqdorlar
- 2.7. Langarlar
- 2.8. Muqobillar va bayroqlar
- 2.9. re.compile va Match
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Asosiy funksiyalar va Match
- Misol 2 — Belgilar sinflari va Unicode
- Misol 3 — Miqdorlar, langarlar, muqobillar, bayroqlar
- Misol 4 — Amaliy: ro'yxatdan o'tish formasini tekshirish
- 5. To'g'ri va noto'g'ri tushunishlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8. Eng yaxshi amaliyotlar
- 9. Amaliy topshiriq
- Xulosa
15.1-dars: Muntazam ifodalar: asoslar
15-QISM — STANDART KUTUBXONA · 1-dars
1. Kirish va motivatsiya
4-qismda satr metodlarini o'rgandik: find, startswith, split, replace. Ular aniq matn bilan ishlaydi. Lekin ko'p vazifada biz aniq matnni emas, shaklni qidiramiz:
- "matndagi barcha telefon raqamlari" — raqamlar har xil, shakli bir xil,
- "
2026-09-17ko'rinishidagi sanalar", - "ketma-ket kelgan bir nechta bo'shliqni bittaga almashtirish",
- "foydalanuvchi nomi faqat harf, raqam va
_dan iborat bo'lsinmi?"
Bularni satr metodlari bilan yozish — o'nlab qator for va if. Muntazam ifoda (regular expression, regex) esa shaklni bir qatorda tasvirlaydi:
re.findall(r"\+998[0-9]{9}", matn) # barcha +998XXXXXXXXX raqamlarReal vaziyat. Ro'yxatdan o'tish formasida ism ^\w+$ bilan tekshirilardi. O'zbek foydalanuvchilar "Oʻgʻiloy" ni oddiy apostrof bilan — O'g'iloy deb yozganda forma "noto'g'ri ism" dedi, chunki ' harf emas. Boshqa tomondan, xuddi shu \d bilan tekshirilgan "yosh" maydoniga kimdir arabcha raqamlar (٢٥) yozdi va ular ham o'tib ketdi. Ikkala xato ham bir sababdan: dasturchi \w va \d aslida nimani bildirishini bilmagan.
Bu darsda muntazam ifodaning tilini o'rganamiz: belgilar, sinflar, miqdorlar, langarlar va bayroqlar — va har birining tuzoqlarini.
Bu darsda:
remodulining asosiy funksiyalari:search,match,fullmatch,findall,finditer- Nega har doim
r"..."— xom satr - Maxsus belgilar va ekranlash,
re.escape - Belgilar sinflari:
[...],\d,\w,\s— va Unicode tuzog'i - Miqdorlar:
*,+,?,{m,n}— ochko'z va dangasa - Langarlar:
^,$,\b,\A,\Z - Muqobillar:
| - Bayroqlar:
IGNORECASE,MULTILINE,DOTALL,VERBOSE,ASCII re.compilevaMatchobyekti
2. Nazariya — chuqur tushuntirish
2.1. Muntazam ifoda nima
Muntazam ifoda — matn shaklini tasvirlovchi kichik til. re moduli bu tildagi naqshni (pattern) holat mashinasiga kompilyatsiya qiladi va matn ustida yurgizadi.
import re
m = re.search(r"\d+", "buyurtma 4521 tayyor")
m.group() # '4521'
m.span() # (9, 13)| Naqshdagi qism | Ma'nosi |
|---|---|
Oddiy belgi (a, 7, -) |
O'zini bildiradi |
| Maxsus belgi (`. ^ $ * + ? { } [ ] \ | ( )`) |
\ + belgi |
Ekranlash yoki maxsus ketma-ketlik |
2.2. Beshta asosiy funksiya
| Funksiya | Qayerda qidiradi | Natija |
|---|---|---|
re.search(p, s) |
Satrning istalgan joyida, birinchisi | Match yoki None |
re.match(p, s) |
Faqat boshidan | Match yoki None |
re.fullmatch(p, s) |
Butun satr mos kelishi kerak | Match yoki None |
re.findall(p, s) |
Hammasi | list[str] |
re.finditer(p, s) |
Hammasi, dangasa | Match iteratori |
Tekshirish (validatsiya) uchun — fullmatch. match faqat boshini tekshiradi: re.match(r"\d+", "123abc") muvaffaqiyatli!
if (m := re.search(naqsh, matn)) is not None:
print(m.group())2.3. Nega r"..." majburiy
Python satrida \ o'zi maxsus (4.10-dars). Regex'da ham. Ikki qatlam to'qnashadi:
| Yozuv | Python ko'radi | Regex ko'radi |
|---|---|---|
"\b" |
Backspace belgisi (1 belgi) | Backspace — so'z chegarasi emas |
r"\b" |
\ va b (2 belgi) |
So'z chegarasi |
"\\b" |
\ va b |
So'z chegarasi (lekin o'qish qiyin) |
re.findall("\bol\b", "ol olma") # [] — jim xato!
re.findall(r"\bol\b", "ol olma") # ['ol'] Qoida: naqshni doim r"..." bilan yozing.
2.4. Ekranlash
Maxsus belgini oddiy belgi sifatida qidirish uchun oldiga \ qo'yiladi:
re.search(r"1\+1", "1+1=2") # '+' — oddiy belgi
re.escape("1+1=2? (ha)") # '1\\+1=2\\?\\ \\(ha\\)' Foydalanuvchi kiritgan matnni naqsh ichiga qo'yayotganda har doim re.escape — aks holda . yoki ( naqshni buzadi yoki kutilmagan narsaga mos keladi.
2.5. Belgilar sinflari
| Yozuv | Ma'nosi |
|---|---|
. |
Istalgan belgi, \n dan tashqari |
[aeiou] |
Shu belgilardan biri |
[a-z0-9] |
Oraliqlar |
[^aeiou] |
Shulardan boshqa istalgan belgi |
\d / \D |
Raqam / raqam emas |
\w / \W |
"So'z belgisi" (harf, raqam, _) / emas |
\s / \S |
Bo'shliq (' ', \t, \n, ...) / emas |
Unicode tuzog'i. Python 3'da str naqshlar sukut bo'yicha Unicode rejimida:
| Yozuv | Sukut (Unicode) | re.ASCII bilan |
|---|---|---|
\d |
5, arabcha ٣, hindcha ७ |
Faqat 0-9 |
\w |
café, тил, oʻzbek |
Faqat [a-zA-Z0-9_] |
\s |
Unicode bo'shliqlari ham | Faqat ASCII bo'shliqlar |
Qiymat aniq 0-9 bo'lishi kerak bo'lsa (karta raqami, PIN, yosh) — [0-9] yoki re.ASCII.
O'zbek matni uchun muhim:
| Yozuv | \w ga kiradimi |
|---|---|
oʻ (U+02BB, rasmiy belgi) |
Harf (Unicode kategoriyasi Lm) |
o' (oddiy apostrof ') |
Tinish belgisi |
o‘ (U+2018, chap tirnoq) |
Tinish belgisi |
re modulida \p{L} (Unicode kategoriyasi) yo'q — re.error beradi. "Faqat harflar" uchun [^\W\d_] ishlatiladi. To'liq Unicode kategoriyalari kerak bo'lsa — tashqi regex kutubxonasi.
2.6. Miqdorlar
| Yozuv | Necha marta |
|---|---|
* |
0 yoki ko'p |
+ |
1 yoki ko'p |
? |
0 yoki 1 |
{3} |
Aynan 3 |
{2,5} |
2 dan 5 gacha |
{2,} |
Kamida 2 |
Ochko'z va dangasa:
| Ochko'z | Dangasa | Farqi |
|---|---|---|
.* |
.*? |
Eng uzun / eng qisqa moslik |
.+ |
.+? |
|
{2,5} |
{2,5}? |
re.findall(r"<.+>", "<b>qalin</b>") # ['<b>qalin</b>'] — ochko'z
re.findall(r"<.+?>", "<b>qalin</b>") # ['<b>', '</b>'] — dangasa * bo'sh moslikka ham mos keladi: re.findall(r"x*", "axxb") → ['', 'xx', '', ''].
2.7. Langarlar
Langar belgi emas, joyni bildiradi.
| Yozuv | Joy |
|---|---|
^ |
Satr boshi (MULTILINE da — har qator boshi) |
$ |
Satr oxiri yoki oxirgi \n oldi |
\A |
Faqat satr boshi |
\Z |
Faqat satr oxiri |
\b |
So'z chegarasi |
\B |
So'z chegarasi emas |
$ oxirgi \n dan oldin ham mos keladi: "abc\n" da $ 3-pozitsiyada, \Z esa 4-pozitsiyada.
2.8. Muqobillar va bayroqlar
| — "yoki". Chapdan o'ngga tekshiriladi va birinchi mos kelgani olinadi:
re.findall(r"kot|kotlin", "kotlin") # ['kot']
re.findall(r"kotlin|kot", "kotlin") # ['kotlin']Bayroqlar:
| Bayroq | Qisqa | Ichki yozuv | Ta'siri |
|---|---|---|---|
re.IGNORECASE |
re.I |
(?i) |
Katta-kichik harf farqsiz |
re.MULTILINE |
re.M |
(?m) |
^/$ har qatorda |
re.DOTALL |
re.S |
(?s) |
. \n ga ham mos |
re.VERBOSE |
re.X |
(?x) |
Bo'shliq va # izohlar |
re.ASCII |
re.A |
(?a) |
\d\w\s faqat ASCII |
Bir nechtasi: re.I | re.M.
2.9. re.compile va Match
TELEFON = re.compile(r"\+998[0-9]{9}")
TELEFON.search(matn); TELEFON.findall(matn)| Fakt | Izoh |
|---|---|
| Modul funksiyalari ham kompilyatsiya qiladi | Ichki keshda saqlanadi (512 tagacha) |
compile ning foydasi |
Nom beradi, bayroqlarni bog'laydi, qayta ishlatiladi |
| Xato naqsh | re.PatternError (3.13+; eski nomi re.error) |
Match obyekti:
| Metod | Natija |
|---|---|
m.group() |
Mos kelgan matn |
m.start(), m.end(), m.span() |
Pozitsiyalar |
bool(m) |
Doim True |
Guruhlar (group(1), nomli guruhlar) — keyingi darsda.
3. Tez ma'lumotnoma
import re
re.search(r"\d+", s) # birinchi moslik yoki None
re.fullmatch(r"[0-9]{4}", s) # butun satr — validatsiya
re.findall(r"\w+", s) # hammasi, ro'yxat
re.finditer(r"\w+", s) # hammasi, Match lar
re.escape(foydalanuvchi_matni) # naqsh ichiga xavfsiz qo'yish
NAQSH = re.compile(r"...", re.I | re.X)Qoidalar
naqsh doim r"..."
validatsiya — fullmatch
aniq 0-9 kerak — [0-9] yoki re.ASCII
foydalanuvchi matni naqshda — re.escape
.* ochko'z — kerak bo'lsa .*?4. Batafsil misollar
Misol 1 — Asosiy funksiyalar va Match
"""search, match, fullmatch farqi; findall va finditer; Match obyekti; xom satr tuzog'i; compile va xato naqsh."""
import re
MATN = "Buyurtma 4521: 3 ta kitob, 12 ta daftar. Jami 185000 so'm."
def main() -> None:
print("=== 1. search, match, fullmatch ===")
for funksiya in (re.search, re.match, re.fullmatch):
for satr in ("4521", "4521-sonli", "buyurtma 4521"):
m = funksiya(r"\d+", satr)
natija = repr(m.group()) if m else "None"
print(f" {funksiya.__name__:9} {satr!r:16} → {natija}")
print(" ⭐ validatsiya uchun faqat fullmatch ishonchli")
print("\n=== 2. findall va finditer ===")
print(f" findall: {re.findall(r'\d+', MATN)}")
for m in re.finditer(r"\d+", MATN):
print(f" finditer: {m.group():>6} span={m.span()}")
print("\n=== 3. Match obyekti ===")
m = re.search(r"\d+", MATN)
assert m is not None
print(f" {m!r}")
print(f" group()={m.group()!r}, start()={m.start()}, end()={m.end()}")
print(f" kesma bilan bir xil: {MATN[m.start():m.end()] == m.group()}")
print(f" bool(m): {bool(m)}, topilmasa: {re.search(r'xyz', MATN)}")
print("\n=== 4. ⚠️ Xom satr tuzog'i ===")
print(f" '\\b' uzunligi: {len('\b')} (backspace), r'\\b' uzunligi: {len(r'\b')}")
print(f" oddiy satr naqsh: {re.findall('\bta\b', MATN)}")
print(f" xom satr naqsh: {re.findall(r'\bta\b', MATN)}")
print("\n=== 5. compile va xato naqsh ===")
SON = re.compile(r"\d+")
print(f" turi: {type(SON).__name__}, naqsh: {SON.pattern!r}")
print(f" SON.findall: {SON.findall('7 va 42')}")
try:
re.compile(r"[0-9")
except re.error as xato:
print(f" {type(xato).__name__}: {xato.msg} (pozitsiya {xato.pos})")
print(f" re.error — PatternError ning eski nomi: {re.error is re.PatternError}")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. search, match, fullmatch ===
search '4521' → '4521'
search '4521-sonli' → '4521'
search 'buyurtma 4521' → '4521'
match '4521' → '4521'
match '4521-sonli' → '4521'
match 'buyurtma 4521' → None
fullmatch '4521' → '4521'
fullmatch '4521-sonli' → None
fullmatch 'buyurtma 4521' → None
⭐ validatsiya uchun faqat fullmatch ishonchli
=== 2. findall va finditer ===
findall: ['4521', '3', '12', '185000']
finditer: 4521 span=(9, 13)
finditer: 3 span=(15, 16)
finditer: 12 span=(27, 29)
finditer: 185000 span=(46, 52)
=== 3. Match obyekti ===
<re.Match object; span=(9, 13), match='4521'>
group()='4521', start()=9, end()=13
kesma bilan bir xil: True
bool(m): True, topilmasa: None
=== 4. ⚠️ Xom satr tuzog'i ===
'\b' uzunligi: 1 (backspace), r'\b' uzunligi: 2
oddiy satr naqsh: []
xom satr naqsh: ['ta', 'ta']
=== 5. compile va xato naqsh ===
turi: Pattern, naqsh: '\\d+'
SON.findall: ['7', '42']
PatternError: unterminated character set (pozitsiya 0)
re.error — PatternError ning eski nomi: TrueNima ko'rsatdi: 2.2, 2.3, 2.9-bo'limlar.
Misol 2 — Belgilar sinflari va Unicode
r"""[...] sinflari; \d \w \s; Unicode va ASCII rejim; o'zbek apostroflari; \p{L} yo'qligi va [^\W\d_]; re.escape."""
import re
import unicodedata
def main() -> None:
print("=== 1. Sinflar ===")
matn = "Dasturlash 2026-yil, narxi $49.99!"
for naqsh in (r"[aeiou]", r"[A-Z]", r"[0-9]+", r"[^\w\s]", r"[.$]"):
print(f" {naqsh:10} → {re.findall(naqsh, matn)}")
print("\n=== 2. ⚠️ \\d sukut bo'yicha Unicode ===")
yoshlar = ["25", "٢٥", "२५", "25a"]
for yosh in yoshlar:
unicode_rejim = bool(re.fullmatch(r"\d+", yosh))
ascii_rejim = bool(re.fullmatch(r"\d+", yosh, re.ASCII))
oraliq = bool(re.fullmatch(r"[0-9]+", yosh))
print(f" {yosh!r:6} \\d+={unicode_rejim!s:5} ASCII={ascii_rejim!s:5} [0-9]+={oraliq}")
print(f" int('٢٥') = {int('٢٥')} ← Python ularni son deb biladi")
print("\n=== 3. ⚠️ O'zbek apostroflari va \\w ===")
variantlar = {"o'zbek": "'", "oʻzbek": "ʻ", "o‘zbek": "‘"}
for soz, belgi in variantlar.items():
nom = unicodedata.name(belgi)
kategoriya = unicodedata.category(belgi)
print(f" {soz:8} {nom:32} [{kategoriya}] \\w+ → {re.findall(r'\w+', soz)}")
print(" ⭐ faqat U+02BB (rasmiy o'zbek belgisi) harf hisoblanadi")
print("\n=== 4. Faqat harflar: \\p{L} o'rniga ===")
try:
re.compile(r"\p{L}+")
except re.error as xato:
print(f" \\p{{L}} → {type(xato).__name__}: {xato.msg}")
matn = "Oʻzbekiston 2026 café_bar тил"
print(f" \\w+ → {re.findall(r'\w+', matn)}")
print(f" [^\\W\\d_]+ → {re.findall(r'[^\W\d_]+', matn)}")
print("\n=== 5. \\s — bo'shliqlar ===")
matn = "a b\tc\nd\u00a0e"
print(f" \\s ga mos keladiganlar: {[hex(ord(b)) for b in re.findall(r'\s', matn)]}")
print(f" ASCII rejimda: {[hex(ord(b)) for b in re.findall(r'\s', matn, re.ASCII)]}")
print(" ⭐ 0xa0 — bo'linmas bo'shliq (veb sahifalardan nusxalanganda ko'p uchraydi)")
print("\n=== 6. re.escape ===")
qidiruv = "narxi $49.99"
xavfli = re.findall(qidiruv, "narxi $49.99 va narxi 49x99")
xavfsiz = re.findall(re.escape(qidiruv), "narxi $49.99 va narxi 49x99")
print(f" re.escape natijasi: {re.escape(qidiruv)!r}")
print(f" ekranlanmagan: {xavfli} ← '$' — satr oxiri, '.' — istalgan belgi")
print(f" ekranlangan: {xavfsiz}")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Sinflar ===
[aeiou] → ['a', 'u', 'a', 'i', 'a', 'i']
[A-Z] → ['D']
[0-9]+ → ['2026', '49', '99']
[^\w\s] → ['-', ',', '$', '.', '!']
[.$] → ['$', '.']
=== 2. ⚠️ \d sukut bo'yicha Unicode ===
'25' \d+=True ASCII=True [0-9]+=True
'٢٥' \d+=True ASCII=False [0-9]+=False
'२५' \d+=True ASCII=False [0-9]+=False
'25a' \d+=False ASCII=False [0-9]+=False
int('٢٥') = 25 ← Python ularni son deb biladi
=== 3. ⚠️ O'zbek apostroflari va \w ===
o'zbek APOSTROPHE [Po] \w+ → ['o', 'zbek']
oʻzbek MODIFIER LETTER TURNED COMMA [Lm] \w+ → ['oʻzbek']
o‘zbek LEFT SINGLE QUOTATION MARK [Pi] \w+ → ['o', 'zbek']
⭐ faqat U+02BB (rasmiy o'zbek belgisi) harf hisoblanadi
=== 4. Faqat harflar: \p{L} o'rniga ===
\p{L} → PatternError: bad escape \p
\w+ → ['Oʻzbekiston', '2026', 'café_bar', 'тил']
[^\W\d_]+ → ['Oʻzbekiston', 'café', 'bar', 'тил']
=== 5. \s — bo'shliqlar ===
\s ga mos keladiganlar: ['0x20', '0x9', '0xa', '0xa0']
ASCII rejimda: ['0x20', '0x9', '0xa']
⭐ 0xa0 — bo'linmas bo'shliq (veb sahifalardan nusxalanganda ko'p uchraydi)
=== 6. re.escape ===
re.escape natijasi: 'narxi\\ \\$49\\.99'
ekranlanmagan: [] ← '$' — satr oxiri, '.' — istalgan belgi
ekranlangan: ['narxi $49.99']Nima ko'rsatdi: 2.4, 2.5-bo'limlar.
Misol 3 — Miqdorlar, langarlar, muqobillar, bayroqlar
r"""Miqdorlar; ochko'z va dangasa; bo'sh moslik; ^ $ \A \Z \b; | tartibi; MULTILINE, DOTALL, IGNORECASE, VERBOSE."""
import re
def main() -> None:
print("=== 1. Miqdorlar ===")
for naqsh in (r"colou?r", r"\d{3}", r"\d{2,3}", r"\d{2,}", r"go+l"):
print(f" {naqsh:9} → {re.findall(naqsh, 'color colour 12345 7 gol gooool gl')}")
print("\n=== 2. Ochko'z va dangasa ===")
html = '<a href="/bosh">Bosh</a> | <a href="/kurs">Kurs</a>'
print(f" <.+> → {re.findall(r'<.+>', html)}")
print(f" <.+?> → {re.findall(r'<.+?>', html)}")
print(f" \"(.*)\" ochko'z uzunligi: {len(re.search(r'\".*\"', html).group())}")
print(f" \"(.*?)\" dangasa: {re.search(r'\".*?\"', html).group()}")
print("\n=== 3. ⚠️ Bo'sh moslik ===")
print(f" x* 'axxb' da: {re.findall(r'x*', 'axxb')}")
print(f" x+ 'axxb' da: {re.findall(r'x+', 'axxb')}")
print("\n=== 4. Langarlar ===")
matn = "ol olma bol ol."
print(f" ol → {len(re.findall(r'ol', matn))} ta")
print(f" \\bol\\b → {len(re.findall(r'\bol\b', matn))} ta (alohida so'z)")
print(f" \\Bol\\b → {re.findall(r'\Bol\b', matn)} (so'z oxirida)")
print(f" '$' 'abc\\n' da pozitsiya: {re.search(r'$', 'abc\n').start()}")
print(f" '\\Z' 'abc\\n' da pozitsiya: {re.search(r'\Z', 'abc\n').start()}")
print(f" ⚠️ fullmatch(r'\\d+$') ham '123\\n' ni o'tkazmaydi: {re.fullmatch(r'\d+$', '123\n')}")
print(f" lekin match(r'\\d+$') o'tkazadi: {bool(re.match(r'\d+$', '123\n'))}")
print("\n=== 5. Muqobillar tartibi ===")
print(f" kot|kotlin → {re.findall(r'kot|kotlin', 'kotlin')}")
print(f" kotlin|kot → {re.findall(r'kotlin|kot', 'kotlin')}")
print(" ⭐ uzunroq muqobilni oldinga qo'ying")
print("\n=== 6. Bayroqlar ===")
jurnal = "XATO: disk\nogoh: xotira\nxato: tarmoq"
print(f" ^xato → {re.findall(r'^xato', jurnal)}")
print(f" ^xato + I → {re.findall(r'^xato', jurnal, re.I)}")
print(f" ^xato: \\w+ + I + M → {re.findall(r'^xato: \w+', jurnal, re.I | re.M)}")
print(f" (?im) ichki yozuv → {re.findall(r'(?im)^xato: \w+', jurnal)}")
print(f" a.b → {re.findall(r'a.b', 'a' + chr(10) + 'b')}, DOTALL bilan → {len(re.findall(r'a.b', 'a' + chr(10) + 'b', re.S))} ta")
print("\n=== 7. VERBOSE — o'qiladigan naqsh ===")
SANA = re.compile(r"""
\b
[0-9]{4} # yil
-
(?:0[1-9]|1[0-2]) # oy: 01-12
-
(?:0[1-9]|[12][0-9]|3[01]) # kun: 01-31
\b
""", re.VERBOSE)
print(f" {SANA.findall('2026-09-17, 2026-13-01, 2026-02-30, 26-09-17')}")
print(" ⚠️ 2026-02-30 o'tdi — regex taqvimni bilmaydi (15.4-dars: datetime)")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Miqdorlar ===
colou?r → ['color', 'colour']
\d{3} → ['123']
\d{2,3} → ['123', '45']
\d{2,} → ['12345']
go+l → ['gol', 'gooool']
=== 2. Ochko'z va dangasa ===
<.+> → ['<a href="/bosh">Bosh</a> | <a href="/kurs">Kurs</a>']
<.+?> → ['<a href="/bosh">', '</a>', '<a href="/kurs">', '</a>']
"(.*)" ochko'z uzunligi: 34
"(.*?)" dangasa: "/bosh"
=== 3. ⚠️ Bo'sh moslik ===
x* 'axxb' da: ['', 'xx', '', '']
x+ 'axxb' da: ['xx']
=== 4. Langarlar ===
ol → 4 ta
\bol\b → 2 ta (alohida so'z)
\Bol\b → ['ol'] (so'z oxirida)
'$' 'abc\n' da pozitsiya: 3
'\Z' 'abc\n' da pozitsiya: 4
⚠️ fullmatch(r'\d+$') ham '123\n' ni o'tkazmaydi: None
lekin match(r'\d+$') o'tkazadi: True
=== 5. Muqobillar tartibi ===
kot|kotlin → ['kot']
kotlin|kot → ['kotlin']
⭐ uzunroq muqobilni oldinga qo'ying
=== 6. Bayroqlar ===
^xato → []
^xato + I → ['XATO']
^xato: \w+ + I + M → ['XATO: disk', 'xato: tarmoq']
(?im) ichki yozuv → ['XATO: disk', 'xato: tarmoq']
a.b → [], DOTALL bilan → 1 ta
=== 7. VERBOSE — o'qiladigan naqsh ===
['2026-09-17', '2026-02-30']
⚠️ 2026-02-30 o'tdi — regex taqvimni bilmaydi (15.4-dars: datetime)Nima ko'rsatdi: 2.6, 2.7, 2.8-bo'limlar.
Misol 4 — Amaliy: ro'yxatdan o'tish formasini tekshirish
Kirishdagi vaziyat: forma maydonlari muntazam ifodalar bilan tekshiriladi. Avval xato qoidalarni ko'rsatamiz va ular qaysi kiritishlarda yanglishishini sanaymiz, keyin tuzatilgan qoidalar bilan takrorlaymiz. Har kiritish uchun "to'g'ri javob" oldindan belgilangan — shuning uchun qoidalarni sinov jadvali bilan baholash mumkin.
"""Forma validatsiyasi: xato qoidalar va tuzatilganlari; sinov jadvali bilan baholash; o'zbek ismlari, raqamlar, telefon, login."""
import re
import unicodedata
XATO_QOIDALAR = {
"ism": re.compile(r"^\w+$"),
"yosh": re.compile(r"\d+"),
"telefon": re.compile(r"\+998\d{9}"),
"login": re.compile(r"[a-z0-9_]{3,16}"),
}
ISM_HARFI = r"[^\W\d_]"
TOGRI_QOIDALAR = {
"ism": re.compile(rf"{ISM_HARFI}+(?:[ʻ'‘`’]{ISM_HARFI}+)*(?:-{ISM_HARFI}+)?"),
"yosh": re.compile(r"[1-9][0-9]?|1[01][0-9]"),
"telefon": re.compile(r"\+998[0-9]{9}"),
"login": re.compile(r"[a-z][a-z0-9_]{2,15}", re.ASCII),
}
# (maydon, kiritish, to'g'ri qabul qilinishi kerakmi)
SINOVLAR = [
("ism", "Aziza", True),
("ism", "Oʻgʻiloy", True),
("ism", "O'g'iloy", True),
("ism", "O‘g‘iloy", True),
("ism", "Anna-Mariya", True),
("ism", "Ali_2", False),
("ism", "Ali\n", False),
("yosh", "25", True),
("yosh", "٢٥", False),
("yosh", "25 yosh", False),
("yosh", "0", False),
("yosh", "119", True),
("telefon", "+998901234567", True),
("telefon", "+9989012345678", False),
("telefon", "tel: +998901234567", False),
("telefon", "+998٩٠١٢٣٤٥٦٧", False),
("login", "aziz_99", True),
("login", "99aziz", False),
("login", "az", False),
("login", "aziz!!", False),
]
def tekshir(qoidalar: dict[str, re.Pattern[str]], maydon: str, qiymat: str, qat_iy: bool) -> bool:
naqsh = qoidalar[maydon]
if qat_iy:
qiymat = unicodedata.normalize("NFC", qiymat)
return naqsh.fullmatch(qiymat) is not None
return naqsh.match(qiymat) is not None
def baholash(nom: str, qoidalar: dict[str, re.Pattern[str]], qat_iy: bool) -> list[str]:
xatolar = []
for maydon, qiymat, kutilgan in SINOVLAR:
if tekshir(qoidalar, maydon, qiymat, qat_iy) != kutilgan:
holat = "o'tkazib yubordi" if not kutilgan else "rad etdi"
xatolar.append(f"{maydon:8} {qiymat!r:24} → {holat}")
print(f" {nom}: {len(SINOVLAR) - len(xatolar)}/{len(SINOVLAR)} to'g'ri")
return xatolar
def main() -> None:
print("=== 1. Xato qoidalar (match, \\w, \\d, langarlarsiz) ===")
for xato in baholash("xato qoidalar", XATO_QOIDALAR, qat_iy=False):
print(f" ❌ {xato}")
print("\n=== 2. Tuzatilgan qoidalar (fullmatch, [0-9], ASCII, apostroflar) ===")
xatolar = baholash("tuzatilgan", TOGRI_QOIDALAR, qat_iy=True)
for xato in xatolar:
print(f" ❌ {xato}")
print(f" hamma sinov o'tdi: {xatolar == []}")
print("\n=== 3. Nima o'zgardi ===")
print(" match → fullmatch: 'tel: ...', '25 yosh', 'aziz!!' endi rad etiladi")
print(" \\d → [0-9]: arabcha raqamlar rad etiladi")
print(" \\w → [^\\W\\d_]: ismda '_' va raqam rad etiladi")
print(" apostrof variantlari: O'g'iloy, Oʻgʻiloy, O‘g‘iloy — hammasi qabul")
print(" re.ASCII (login): faqat lotin harflari")
print("\n=== 4. ⚠️ Regex nimani tekshirmaydi ===")
print(" telefon raqami haqiqatan mavjudmi — yo'q (SMS kod kerak)")
print(" yosh mantiqiymi (ro'yxatdan o'tish sanasiga nisbatan) — yo'q")
print(" ⭐ regex — shakl tekshiruvi; ma'no tekshiruvi — alohida qatlam (13.8-dars)")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Xato qoidalar (match, \w, \d, langarlarsiz) ===
xato qoidalar: 8/20 to'g'ri
❌ ism "O'g'iloy" → rad etdi
❌ ism 'O‘g‘iloy' → rad etdi
❌ ism 'Anna-Mariya' → rad etdi
❌ ism 'Ali_2' → o'tkazib yubordi
❌ ism 'Ali\n' → o'tkazib yubordi
❌ yosh '٢٥' → o'tkazib yubordi
❌ yosh '25 yosh' → o'tkazib yubordi
❌ yosh '0' → o'tkazib yubordi
❌ telefon '+9989012345678' → o'tkazib yubordi
❌ telefon '+998٩٠١٢٣٤٥٦٧' → o'tkazib yubordi
❌ login '99aziz' → o'tkazib yubordi
❌ login 'aziz!!' → o'tkazib yubordi
=== 2. Tuzatilgan qoidalar (fullmatch, [0-9], ASCII, apostroflar) ===
tuzatilgan: 20/20 to'g'ri
hamma sinov o'tdi: True
=== 3. Nima o'zgardi ===
match → fullmatch: 'tel: ...', '25 yosh', 'aziz!!' endi rad etiladi
\d → [0-9]: arabcha raqamlar rad etiladi
\w → [^\W\d_]: ismda '_' va raqam rad etiladi
apostrof variantlari: O'g'iloy, Oʻgʻiloy, O‘g‘iloy — hammasi qabul
re.ASCII (login): faqat lotin harflari
=== 4. ⚠️ Regex nimani tekshirmaydi ===
telefon raqami haqiqatan mavjudmi — yo'q (SMS kod kerak)
yosh mantiqiymi (ro'yxatdan o'tish sanasiga nisbatan) — yo'q
⭐ regex — shakl tekshiruvi; ma'no tekshiruvi — alohida qatlam (13.8-dars)Nima ko'rsatdi: 2.2, 2.5, 2.6, 2.7-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
"re.match butun satrni tekshiradi" |
Faqat boshini; butun satr — fullmatch |
"\d — 0-9" |
Sukut bo'yicha har qanday Unicode raqam |
"\w — lotin harflari" |
Unicode harflari, raqamlar va _ |
"o'zbek — bitta \w+ so'z" |
Oddiy apostrof harf emas |
""\b" va r"\b" bir xil" |
Birinchisi — backspace belgisi |
". istalgan belgi" |
\n dan tashqari (DOTALL siz) |
"$ — satrning eng oxiri" |
Oxirgi \n oldida ham mos keladi |
"re da \p{L} bor" |
Yo'q — [^\W\d_] yoki regex kutubxonasi |
6. Keng tarqalgan xatolar va yechimlari
1. Oddiy satr naqsh
re.findall("\bso'z\b", matn) # ❌ backspace
re.findall(r"\bso'z\b", matn) # ✅2. Validatsiyada match yoki search
if re.match(r"\d+", yosh): ... # ❌ '25abc' o'tadi
if re.fullmatch(r"[0-9]+", yosh): ... # ✅3. Foydalanuvchi matni ekranlanmagan
re.search(qidiruv, matn) # ❌ 'c++' → xato naqsh
re.search(re.escape(qidiruv), matn) # ✅4. Ochko'z .*
re.findall(r'"(.*)"', matn) # ❌ birinchi va oxirgi qo'shtirnoq orasini oladi
re.findall(r'"(.*?)"', matn) # ✅ yoki [^"]*5. Muqobillar tartibi
r"kot|kotlin" # ❌ 'kotlin' da 'kot'
r"kotlin|kot" # ✅6. Topilmaganini tekshirmaslik
re.search(naqsh, matn).group() # ❌ AttributeError: 'NoneType'
if (m := re.search(naqsh, matn)): m.group() # ✅7. $ bilan qator oxirini tekshirish
re.match(r"[0-9]+$", "123\n") # ⚠️ o'tadi
re.fullmatch(r"[0-9]+", "123\n") # ✅ o'tmaydi8. HTML/JSON ni regex bilan tahlil qilish
re.findall(r"<div>(.*?)</div>", html) # ⚠️ ichma-ich teglar buziladi
# ✅ html.parser, BeautifulSoup, json (16-qism)7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 4-qism (o'tilgan): satr metodlari, xom satrlar, Unicode
- 13.8-dars (o'tilgan):
pydanticdapattern=bilan validatsiya - 15.2-dars: guruhlar,
sub,split - 15.3-dars: amaliy naqshlar, lookahead, ishlash tezligi
- 16-qism: matn va CSV fayllarni tozalash
- 17-qism: testlarda chiqishni tekshirish
- 20.4-dars: route va parametrlar
- 24-qism: ma'lumotlarni tozalash (
pandas.str.extract)
8. Eng yaxshi amaliyotlar
Naqshni doim
r"..."bilan yozing.Validatsiya —
fullmatch.Aniq ASCII kerak bo'lsa —
[0-9],re.ASCII.Foydalanuvchi matnini
re.escapeqiling.Murakkab naqshlarni
re.VERBOSEva izohlar bilan yozing.Tez-tez ishlatiladigan naqshga nom bering —
TELEFON = re.compile(...).Naqshni sinov jadvali bilan tekshiring — "o'tishi kerak" va "o'tmasligi kerak" misollar.
Regex hamma narsaga javob emas: oddiy holatlarda
startswith,in,isdigit; tuzilgan formatlarda — parser.
9. Amaliy topshiriq
Vazifa 1: Natijani bashorat qiling
import re
1. print(re.findall(r"\d+", "a1b22c333"))
2. print(re.match(r"\d+", "abc123"))
3. print(re.search(r"\d+", "abc123").group())
4. print(bool(re.fullmatch(r"\d+", "123abc")))
5. print(re.findall(r"a.c", "abc a\nc aXc"))
6. print(re.findall(r"<.*?>", "<p><b>"))
7. print(re.findall(r"\bis\b", "this is his island"))
8. print(re.findall(r"[^aeiou]", "audio"))
9. print(len("\n"), len(r"\n"))
10. print(re.findall(r"\w+", "o'rik"))
11. print(bool(re.fullmatch(r"\d", "٣")), bool(re.fullmatch(r"[0-9]", "٣")))
12. print(re.escape("a.b"))Javoblar
['1', '22', '333']None—matchfaqat boshidan123False['abc', 'aXc']—.\nga mos kelmaydi['<p>', '<b>']['is']—this,his,islandichidagisi so'z chegarasida emas['d']1 2['o', 'rik']— oddiy apostrof harf emasTrue Falsea\.b
Vazifa 2: Xatolarni tuzating
1. def pochta_indeksimi(s):
return re.match("\d{6}", s) is not None
2. def qidir(soz, matn):
return re.findall(soz, matn) # soz = "c++"
3. def sarlavha(html):
return re.search(r"<title>(.*)</title>", html).group()
4. def yil(s):
return re.fullmatch(r"\d{4}", s) # "٢٠٢٦" ham o'tadi
5. FAYL = r"rasm|rasmlar"
re.findall(FAYL, "rasmlar papkasi")Javoblar
1. def pochta_indeksimi(s):
return re.fullmatch(r"[0-9]{6}", s) is not None # r"", fullmatch, [0-9]
2. def qidir(soz, matn):
return re.findall(re.escape(soz), matn)
3. def sarlavha(html):
m = re.search(r"<title>(.*?)</title>", html, re.S | re.I)
return m.group() if m else None # None tekshiruvi, dangasa
4. def yil(s):
return re.fullmatch(r"[0-9]{4}", s)
5. FAYL = r"rasmlar|rasm" # uzunrog'i oldindaVazifa 3: Naqsh sinovchisi
naqsh_sinovi(naqsh, otishi_kerak, otmasligi_kerak) funksiyasini yozing:
fullmatchbilan har bir misolni tekshirsin- Xato natijalarni jadvalda ko'rsatsin
- Naqsh kompilyatsiya bo'lmasa —
PatternErrorxabari va pozitsiyasini chiqarsin - O'zbek avtomobil raqami (
01 A 123 AA,01 123 AAA) uchun naqsh yozib, 10 ta ijobiy va 10 ta salbiy misol bilan sinang
Vazifa 4: Matn statistikasi
Berilgan o'zbekcha matn uchun:
- So'zlar soni — apostrofli so'zlar (
o'zbek,g'alaba) bitta so'z hisoblansin - Eng ko'p uchragan 10 so'z (katta-kichik harf farqsiz)
- Sonlar va ularning yig'indisi
- Gaplar soni (
.,!,?bilan tugaydi, lekin3.14ichidagi nuqta emas) - Natijani
split()asosidagi sodda usul bilan solishtiring
Vazifa 5: Apostrofni me'yorlash
- Matndagi
o',g'va ularning variantlarini (',‘,’,`,ʼ) topsin - Hammasini rasmiy
ʻ(U+02BB) ga almashtirsin — faqatovagdan keyin sh'kabi tutuq belgisini (ma'no,san'at)ʼ(U+02BC) ga almashtirsin- Almashtirishlar sonini hisoblasin
- 20 ta real jumla bilan sinang (almashtirish — keyingi darsdagi
re.sub; hozirchafinditerva satr yig'ish bilan)
Vazifa 6: Jurnal filtri
Server jurnali (kamida 50 qator) uchun:
ERRORvaCRITICALqatorlarni katta-kichik harf farqsiz toping (MULTILINE)- IP manzillarni ajrating (to'rt qism, har biri 0–255 — faqat shakl)
- Vaqt belgilarini (
2026-09-17 14:03:22) toping - Bitta naqshni
VERBOSErejimida izohlar bilan yozing - Har naqsh uchun sinov jadvali tuzing
Vazifa 7: O'ylash
Muntazam ifodalar 1950-yillarda matematik Stiven Klini tomonidan formal tillar nazariyasida kiritilgan. Nazariyada "muntazam til"ni qavslar balansini ((()())) tekshira olmaydigan mashina taniydi. Python'dagi re esa backreference (\1) kabi imkoniyatlarga ega. Nega HTML'ni regex bilan tahlil qilish "yomon g'oya" deyiladi va bu nazariya bilan qanday bog'liq?
Javob
Qisqa javob: Nazariy muntazam ifodalar cheklangan xotirali mashina (cheklangan avtomat) bilan tanilanadi — u ichma-ich tuzilmalarni (qavslar, HTML teglari) sanay olmaydi. HTML esa ichma-ich tuzilgan — uni tahlil qilish uchun stek (kontekstsiz grammatika) kerak. Python'ning re i nazariyadan kuchliroq (backreference), lekin baribir ichma-ich tuzilmalar uchun mo'ljallanmagan va bunday naqshlar mo'rt, sekin va xavfli bo'ladi.
1. Nazariya: Xomskiy ierarxiyasi
| Til turi | Taniydigan mashina | Misol |
|---|---|---|
| Muntazam | Cheklangan avtomat (xotira yo'q) | Telefon raqami, sana shakli |
| Kontekstsiz | Stekli avtomat | Qavslar balansi, HTML, JSON, Python kodi |
| Kontekstga bog'liq | Chiziqli chegaralangan mashina | Ba'zi dasturlash tillari qoidalari |
| Rekursiv sanaladigan | Tyuring mashinasi | Istalgan hisoblash |
2. Nega qavslarni sanab bo'lmaydi
Cheklangan avtomatning holatlari soni qat'iy, masalan N ta. N+1 ta ochiq qavsdan keyin u nechta ochilganini "eslay" olmaydi — ikki xil chuqurlik bitta holatga tushadi (Dirixle prinsipi). Demak (((...))) ni istalgan chuqurlikda to'g'ri tekshira olmaydi.
3. Python'ning re i nazariyadan kuchli
\1(backreference) — "avval topilgan narsa yana takrorlansin":(\w+) \1— bu muntazam til emas- Lookahead / lookbehind (15.3-dars)
- Lekin rekursiya yo'q:
reda(?R)yo'q (tashqiregexkutubxonasida bor) - Shuning uchun
reichma-ich teglarni umumiy holda tahlil qila olmaydi
4. HTML ni regex bilan tahlil qilish muammolari
| Muammo | Misol |
|---|---|
| Ichma-ich teglar | <div><div>a</div>b</div> — <div>(.*?)</div> birinchi yopilishda to'xtaydi |
| Atributlar tartibi va qo'shtirnoqlar | <a class="x" href='y'>, href=y |
Izohlar va <script> |
<!-- <div> -->, JavaScript ichidagi </div> satri |
| Buzilgan HTML | Brauzerlar tuzatadi, regex esa yo'q |
| Katastrofik backtracking | Murakkab naqsh eksponensial sekinlashadi (15.3-dars) |
5. To'g'ri yondashuv
| Vazifa | Vosita |
|---|---|
| HTML | html.parser, BeautifulSoup, lxml |
| JSON | json (16.2-dars) |
| Python kodi | ast |
| Qavslar balansi | Stek bilan oddiy tsikl |
| Tokenlar (so'z, son, belgi) | Regex — ideal (15.3-dars: tokenizator) |
Amaliy qoida: regex leksik darajada (tokenlar, shakllar) juda yaxshi; sintaktik daraja (tuzilma, ichma-ichlik) uchun parser kerak. Ko'p parserlar ichida regex tokenizator ishlaydi.
6. Xulosa
- Nazariy muntazam ifodalar xotirasiz mashinaga teng — ichma-ichlikni sanay olmaydi
rebackreference bilan kuchliroq, lekin rekursiv tuzilmalar uchun emas- HTML/JSON/kod uchun parser, tokenlar uchun regex
- "Regex bilan HTML" — ba'zan kichik bir martalik skriptda ishlaydi, lekin ishonchli tizimda emas
Nimani mustahkamlaydi: 2.1–2.9-bo'limlar.
Xulosa
Bu darsda muntazam ifodalar tilining asoslarini o'rgandik.
Eng muhim uch fikr:
To'g'ri funksiya va xom satr.
searchistalgan joydan,matchfaqat boshidan,fullmatchbutun satrni tekshiradi — validatsiya uchun faqatfullmatchishonchli. Naqsh doimr"..."bilan yoziladi: oddiy satrda"\b"backspace belgisiga aylanib, naqsh jimgina hech narsa topmaydi. Foydalanuvchi matni naqshgare.escapeorqali qo'yiladi.\d,\w,\s— Unicode. Sukut bo'yicha\darabcha va hindcha raqamlarni,\wesa har qanday alifbo harflarini qabul qiladi. Aniq0-9kerak bo'lsa —[0-9]yokire.ASCII. O'zbek matnida faqat rasmiyʻ(U+02BB) harf hisoblanadi, oddiy'esa so'zni ikkiga bo'ladi.reda\p{L}yo'q — "faqat harflar" uchun[^\W\d_].Miqdorlar, langarlar va bayroqlar naqsh ma'nosini tubdan o'zgartiradi.
.*ochko'z — eng uzun moslikni oladi,.*?dangasa — eng qisqasini.$oxirgi\ndan oldin ham mos keladi,|esa birinchi mos kelgan muqobilni oladi.MULTILINE,DOTALL,IGNORECASEva o'qiladigan naqshlar uchunVERBOSE— har kungi vositalar.
Keyingi darsda naqshdan ma'lumot ajratib olishni o'rganamiz: guruhlar, nomli guruhlar, re.sub bilan almashtirish va re.split.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!