Skip to content

Commit c8428a1

Browse files
author
Saeid Darvish
committed
l16: sub, l15: Zero-length Match
1 parent d991548 commit c8428a1

2 files changed

Lines changed: 102 additions & 0 deletions

File tree

lessons/l15.rst

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,18 @@
372372
[`regex101@ تست آنلاین <https://regex101.com/r/IIc4Fh/17>`__]
373373

374374

375+
.. tip::
376+
این کاراکتر (``b\``) در مبحث RegEx به عنوان انطباق‌گر یک word(``\w``) boundary نیز خوانده می‌شود. word boundary (مرز واژه) به سه موقعیت گفته میشود:
377+
378+
* قبل از نخستین کاراکتر، زمانی که کاراکتر نخست یکی از کاراکترهای شامل ``w\`` باشد
379+
* بعد از کاراکتر پایانی، زمانی که کاراکتر پایانی یکی از کاراکترهای شامل ``w\`` باشد
380+
* بین دو کاراکتر، زمانی که یکی از این دو کارامتر شامل ``w\`` باشد ولی دیگری خیر
381+
382+
[`regex101@ تست آنلاین <https://regex101.com/r/48XLbY/1>`__] در این نمونه کد، نقاط word boundary مشخص شده است
383+
384+
در ادمه کارکتر ``w\`` شرح داده خواهد شد.
385+
386+
375387
* ``B\``
376388

377389
برعکس ``b\``، بر حسب موقعیت قرار گرفتن، شروع یا پایان **نیافتن** یک **کلمه** را مشخص می‌کند. یعنی کلماتی را تطبیق می‌دهد که با کاراکتر یا کارکترهایی مشخصی شروع یا پایان نیافته باشند.
@@ -397,6 +409,9 @@
397409

398410
[`regex101@ تست آنلاین <https://regex101.com/r/IIc4Fh/19>`__]
399411

412+
.. tip::
413+
این کاراکتر (``B\``) در تضاد با ``b\`` به عنوان انطباق‌گر نقاطی که word(``\w``) boundary **نیستند**، نیز خوانده می‌شود. [`regex101@ تست آنلاین <https://regex101.com/r/M3f3VN/1>`__]
414+
400415

401416
* ``d\``
402417

@@ -521,6 +536,32 @@
521536

522537

523538

539+
انطباق با طول صفر (Zero-length Match)
540+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
541+
542+
یک عبارت Zero-length به عبارتی از مبحث RegEx گفته می‌شود که هیچ کاراکتری را انطباق نمی‌دهد بلکه تنها موقعیت‌هایی را در متن رشته مورد نظر تطبیق می‌دهد. برای نمونه متن رشته ``1,2`` را درنظر بگیرید، الگو ``b\`` تنها موقعیت‌های قبل از ``1``، بین ``1`` و ``,``، بین ``,`` و ``2`` و بعد از ``2`` را تطبیق می‌دهد؛ در نتیجه الگو ``b\`` برای این متن یک Zero-length Match است. [به نتایج دقت کنید: `regex101@ تست آنلاین <https://regex101.com/r/BCuLmh/1>`__] . Zero-length Match در RegEx بسیار گمراه کننده هستند و می‌بایست با دقت از آن‌ها استفاده کرد. در زیر چند نمونه الگو از Zero-length Match‌ها ارايه شده است::
543+
544+
\b
545+
\B
546+
\A
547+
\B
548+
^
549+
$
550+
.*
551+
\d*
552+
553+
سعی کنید برای الگوهای بالا در regex101.com، متن‌هایی را مثال بزنید، تست کنید و نتایج را با دقت مشاهده نمایید، به عنوان مثالی دیگر الگو زیر را در نظر بگیرید - این مورد را با هم بررسی می‌کنیم::
554+
555+
p*
556+
557+
حاصل انطباق این الگو برای متنی مانند ``1,2`` هیچ فرق با الگو ``b\`` (که پیش‌تر صحبت شد) ندارد - تا اینجا فهمیدیم که از دید RegEx متن تنها همان کاراکترهای قابل دید نیست بلکه نقاطی مثل قبل از کاراکتر نخست، بعد از کاراکتر پایانی و حتی گاهی بین دو کاراکتر را نیز در نظر می‌گیرد و همچنین می‌دانیم که این الگو به دنبال هیچ یا هربار تکرار کاراکتر ``p`` در متن است. در نتیجه نقاطی که شامل هیچ کاراکتری نباشد یا شامل کاراکتر ``p`` باشد تطبیق پیدا می‌کند و از آنجایی که متن مورد نظر شامل ``p`` نمی‌باشد، تنها موقعیت‌های Zero-length باقی می‌ماند! - این الگو برای متن یاد شده کاملا یک Zero-length Match است.
558+
559+
[`regex101@ تست آنلاین <https://regex101.com/r/OQrGDE/1>`__] (p در این الگو تنها یک کاراکتر متنی است - کاراکترهای دیگر را نیز خودتان تست کنید)
560+
561+
562+
563+
564+
524565

525566
ماژول re پایتون
526567
-----------------
@@ -836,6 +877,10 @@
836877
YES
837878

838879

880+
.. note::
881+
882+
قالب‌های Lookahead یا Lookbehind (در کل lookaround‌ها) را نیز می‌توان از نوع Zero-Lengthها در نظر گرفت تنها تفاوت آن‌ها با الگوهایی که پیش‌تر بیان شد این است که lookaround‌ها ابتدا کاراکتر(هایی) را تطبیق و سپس از آن(ها) گذر می‌کنند.
883+
839884

840885
|
841886

lessons/l16.rst

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,63 @@
589589

590590
``sub(pattern, repl, string, count=0, flags=0)``
591591

592+
این تابع (``sub``) حاصل انطباق‌های ممکن pattern در string را در repl جایگذاری می‌کند. این تابع همچنین دو پارامتر اختیاری دارد (flags و count)، پیش‌تر در مورد flags صحبت کردیم و count نیز بیانگر ماکزیمم تعداد انطباقی است که می‌خواهیم در repl جایگذاری شود - این مقدار می‌بایست یک عدد مثبت باشد و مقدار صفر (مقدار پیش‌فرض) برای آن به معنی هر تعداد (نامحدود) خواهد بود. پارامتر repl در این تابع می‌تواند از نوع رشته یا تابع باشد، ابتدا حالت رشته را بررسی می‌کنیم [`اسناد پایتون <https://docs.python.org/3/library/re.html#re.sub>`__]::
593+
594+
>>> import re # Python 3.x
595+
596+
>>> string = 'Perl@1987,Python@1991,Ruby@1995'
597+
>>> repl = ' - '
598+
>>> pattern = r'@\d+,?'
599+
600+
>>> result = re.sub(pattern, repl, string)
601+
602+
>>> type(result)
603+
<class 'str'>
604+
605+
>>> print(result)
606+
Perl - Python - Ruby -
607+
608+
>>> result = re.sub(pattern, repl, string, 2) # count=2
609+
>>> print(result)
610+
Perl - Python - Ruby@1995
611+
612+
>>> result = re.sub(pattern, repl, string, 1) # count=1
613+
>>> print(result)
614+
Perl - Python@1991,Ruby@1995
615+
616+
متد ``expand`` از شی Match که در ابتدای این درس مطرح شد را بیاد بیاورید، بدیهی است که pattern می‌تواند شامل گروهبندی نیز باشد، در این شرایط آنچه از قوانین موجود در پارامتر template متد ``expand`` گفته شد در repl (در حالتی که یک شی رشته است) نیز صدق می‌کند::
617+
618+
>>> result = re.sub(r'(\w+),(\w+),(\w+)', r'(\1) (\2) (\3)', 'Jazz,Rock,Pop')
619+
>>> print(result)
620+
(Jazz) (Rock) (Pop)
621+
622+
>>> re.sub(r'(\w+),(\w+),(\w+)', r'(\g<1>) (\g<2>) (\g<3>)', 'Jazz,Rock,Pop')
623+
'(Jazz) (Rock) (Pop)'
624+
625+
626+
::
627+
628+
>>> re.sub(r'(?P<num>\d+)', r'#\g<num>#', 'Top 100 songs')
629+
'Top #100# songs'
630+
631+
به مثالی دیگر توجه نمایید::
632+
633+
>>> re.sub('x*', '-', 'abc@123,456')
634+
'-a-b-c-@-1-2-3-,-4-5-6-'
635+
636+
الگو مورد استفاده برای متن مثال بالا یک Zero-length Match است (درس قبل) - [`regex101@ تست آنلاین <https://regex101.com/r/n0I6JU/1>`__]
637+
638+
639+
.. tip::
640+
641+
چنانچه تابع ``sub`` هیچ انطباقی از pattern در string پیدا نکند، مقدار string را بدون تغییر برمی‌گرداند::
642+
643+
>>> re.sub(r'\d', '-', 'abc@xyz') # Without matching
644+
'abc@xyz'
645+
646+
>>> re.sub(r'\d', '-', 'abc@123')
647+
'abc@---'
648+
592649

593650

594651

0 commit comments

Comments
 (0)