GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||
GeezerVison is showing python.github.io — re --- عملیات عبارت باقاعده
|
زمینهی ارجاع به گروه «quote» |
راههای ارجاع به آن |
|---|---|
در خودِ همان الگو |
|
هنگام پردازش شیء تطبیق m |
|
در رشتهای که به آرگومان repl از |
|
تغییر یافته در نسخهی 3.12: در الگوهای bytes، نام گروه فقط میتواند شامل بایتهایی در محدوده ASCII (b'\x00'-b'\x7f') باشد.
(?P=name)¶یک ارجاع به عقب (backreference) به یک گروه نامدار؛ با هر متنی که گروه پیشین با نام name با آن مطابقت کرده است، مطابقت میکند.
(?#...)¶یک کامنت؛ محتوای پرانتزها بهسادگی نادیده گرفته میشود.
(?=...)¶در صورتی تطابق مییابد که ... در ادامه تطابق یابد، اما هیچ بخشی از رشته را مصرف نمیکند. این یک ادعای پیشنگر (lookahead assertion) نامیده میشود. برای مثال، Isaac (?=Asimov) تنها در صورتی با 'Isaac ' تطابق مییابد که پس از آن 'Asimov' آمده باشد.
(?!...)¶در صورتی مطابقت میکند که ... در ادامه مطابقت نکند. این یک ادعای پیشنگری منفی (negative lookahead assertion) است. برای مثال، Isaac (?!Asimov) تنها در صورتی با 'Isaac ' مطابقت میکند که پس از آن 'Asimov' نیامده باشد.
(?<=...)¶در صورتی مطابقت میکند که موقعیت فعلی در رشته، بلافاصله پس از یک مطابقت برای ... باشد که در همان موقعیت فعلی پایان مییابد. به این اصطلاح، ادعای پسنگر مثبت (positive lookbehind assertion) گفته میشود. (?<=abc)def یک مطابقت در 'abcdef' پیدا میکند، زیرا پسنگر ۳ نویسه به عقب برمیگردد و بررسی میکند که آیا الگوی داخلی مطابقت دارد یا خیر. الگوی داخلی باید فقط با رشتههایی با طول ثابت مطابقت کند، به این معنا که abc یا a|b مجاز هستند، اما a* و a{3,4} مجاز نیستند. توجه داشته باشید که الگوهایی که با ادعاهای پسنگر مثبت شروع میشوند، در ابتدای رشتهای که جستجو میشود مطابقت نخواهند کرد؛ به احتمال زیاد میخواهید به جای تابع match() از تابع search() استفاده کنید:
>>> import re >>> m = re.search('(?<=abc)def', 'abcdef') >>> m.group(0) 'def'
این مثال به دنبال کلمهای میگردد که پس از خط تیره آمده باشد:
>>> m = re.search(r'(?<=-)\w+', 'spam-egg') >>> m.group(0) 'egg'
تغییر یافته در نسخهی 3.5: پشتیبانی از ارجاعهای گروه با طول ثابت اضافه شد.
(?<!...)¶در صورتی مطابقت میکند که موقعیت فعلی در رشته، پیش از خود، مطابقتی برای ... نداشته باشد. به این مورد ادعای پسنگر منفی (negative lookbehind assertion) گفته میشود. مانند ادعاهای پسنگر مثبت، الگوی درون آن باید فقط با رشتههایی با طول ثابت مطابقت کند. الگوهایی که با ادعاهای پسنگر منفی آغاز میشوند، ممکن است در ابتدای رشتهی مورد جستجو مطابقت کنند.
(?(id/name)yes-pattern|no-pattern)¶اگر گروه با id یا name دادهشده وجود داشته باشد، تلاش میشود با yes-pattern تطبیق داده شود، و در غیر این صورت با no-pattern. no-pattern اختیاری است و میتوان آن را حذف کرد. برای مثال، (<)?(\w+@\w+(?:\.\w+)+)(?(1)>|$) الگوی تطبیق ایمیل ضعیفی است که هم با '<[email protected]>' و هم با '[email protected]' تطبیق میکند، اما با '<[email protected]' و '[email protected]>' بهطور کامل تطبیق نمیکند (re.search() در مورد نخست فقط '[email protected]' را پیدا میکند).
تغییر یافته در نسخهی 3.12: شناسهی گروه id فقط میتواند شامل ارقام ASCII باشد. در الگوهای bytes، نام گروه name فقط میتواند شامل بایتهایی در محدودهی ASCII (b'\x00'-b'\x7f') باشد.
دنبالههای ویژه شامل '\' و یک نویسه از فهرست زیر هستند. اگر نویسه معمولی یک رقم ASCII یا یک حرف ASCII نباشد، عبارت باقاعده حاصل با دومین نویسه تطابق خواهد داشت. برای مثال، \$ با نویسه '$' تطابق دارد.
\number¶با محتوای گروهی با همان شماره تطابق دارد. شمارهگذاری گروهها از ۱ شروع میشود. برای مثال، (.+) \1 با 'the the' یا '55 55' تطابق دارد، اما با 'thethe' تطابق ندارد (به فاصله بعد از گروه توجه کنید). این دنباله خاص فقط میتواند برای تطابق با یکی از ۹۹ گروه اول استفاده شود. اگر نخستین رقم number ۰ باشد، یا number ۳ رقم مبنای هشت داشته باشد، بهعنوان تطابق گروهی تفسیر نمیشود، بلکه بهعنوان نویسهای با مقدار مبنای هشت number تفسیر میشود. در داخل '[' و ']' یک کلاس نویسهای، تمام گریزهای عددی بهعنوان نویسه در نظر گرفته میشوند.
\A¶تنها در ابتدای رشته تطابق مییابد.
\b¶با رشتهی خالی مطابقت دارد، اما فقط در آغاز یا پایان یک واژه. یک واژه بهعنوان دنبالهای از نویسههای واژه تعریف میشود. توجه داشته باشید که بهصورت رسمی، \b بهعنوان مرز بین یک نویسهی \w و یک نویسهی \W (یا برعکس)، یا بین \w و آغاز یا پایان رشته تعریف شده است. این یعنی r'\bat\b' با 'at'، 'at.'، '(at)' و 'as at ay' مطابقت دارد، اما با 'attempt' یا 'atlas' مطابقت ندارد.
نویسههای پیشفرض کلمه در الگوهای یونیکد (str)، نویسههای الفبایی و عددی یونیکد و زیرخط هستند، اما میتوان آنها را با استفاده از پرچم ASCII تغییر داد. در صورت استفاده از پرچم LOCALE، مرزهای کلمه بر اساس locale فعلی تعیین میشوند.
نکته
در داخل یک بازهی نویسه، \b برای سازگاری با مقادیر لفظی رشتهای پایتون، نویسهی پسبر را نشان میدهد.
\B¶با رشته خالی تطابق دارد، اما فقط زمانی که در آغاز یا پایان یک کلمه نباشد. این بدان معناست که r'at\B' با 'athens'، 'atom'، 'attorney' تطابق دارد، اما با 'at'، 'at.' یا 'at!' تطابق ندارد. \B مخالف \b است، بنابراین نویسههای کلمه در الگوهای Unicode (str)، نویسههای الفباییعددی Unicode یا نویسهی زیرخط هستند، اگرچه میتوان این را با استفاده از پرچم ASCII تغییر داد. مرزهای کلمه در صورت استفاده از پرچم LOCALE بر اساس تنظیمات locale تعیین میشوند.
تغییر یافته در نسخهی 3.14: \B اکنون با رشتهی ورودی خالی مطابقت دارد.
\d¶با هر رقم اعشاری یونیکد مطابقت دارد (یعنی هر نویسه در ردهی نویسهای یونیکد [Nd]). این شامل [0-9] و همچنین بسیاری از نویسههای رقمی دیگر نیز میشود.
در صورت استفاده از پرچم ASCII، با [0-9] مطابقت میکند.
با هر رقم دهدهی در مجموعهنویسهی ASCII مطابقت دارد؛ این معادل [0-9] است.
\D¶با هر نویسهای که رقم دهدهی نیست، مطابقت میکند. این مخالف \d است.
در صورت استفاده از پرچم ASCII، با [^0-9] مطابقت میکند.
\s¶با نویسههای فضای سفید یونیکد (طبق تعریف str.isspace()) مطابقت دارد. این شامل [ \t\n\r\f\v] و همچنین بسیاری از نویسههای دیگر، برای مثال فاصلههای نشکنی است که قواعد حروفچینی در بسیاری از زبانها آنها را الزامی میدانند.
اگر از پرچم ASCII استفاده شود، با [ \t\n\r\f\v] مطابقت دارد.
با نویسههایی که در مجموعه نویسههای ASCII فضای سفید در نظر گرفته میشوند، تطابق دارد؛ این معادل [ \t\n\r\f\v] است.
\S¶با هر نویسهای که نویسهی فضای خالی نباشد، تطابق مییابد. این متضاد \s است.
اگر پرچم ASCII استفاده شود، با [^ \t\n\r\f\v] مطابقت دارد.
\w¶با نویسههای واژه در یونیکد مطابقت دارد؛ این شامل تمام نویسههای الفباییعددی یونیکد (طبق تعریف str.isalnum()) و همچنین زیرخط (_) میشود.
در صورت استفاده از پرچم ASCII، با [a-zA-Z0-9_] مطابقت میکند.
با نویسههایی که در مجموعه نویسههای ASCII الفباییعددی محسوب میشوند، مطابقت دارد؛ این معادل [a-zA-Z0-9_] است. اگر از پرچم LOCALE استفاده شود، با نویسههایی که در locale فعلی الفباییعددی محسوب میشوند و نیز با نویسه زیرخط مطابقت دارد.
\W¶با هر نویسهای که نویسه واژگانی نیست، تطابق دارد. این معکوس \w است. بهطور پیشفرض، با نویسههای غیر از زیرخط (_) که str.isalnum() برای آنها False برمیگرداند، تطابق دارد.
اگر از پرچم ASCII استفاده شود، با [^a-zA-Z0-9_] مطابقت میکند.
اگر پرچم LOCALE استفاده شود، با نویسههایی مطابقت میکند که در تنظیمات locale جاری، نه الفباییعددی هستند و نه زیرخط.
\z¶تنها در پایان رشته تطابق میکند.
اضافه شده در نسخهی 3.14.
\Z¶مشابه \z. برای سازگاری با نسخههای قدیمی پایتون.
بیشتر دنبالههای خنثیسازی پشتیبانیشده توسط رشتهنوشتههای پایتون، توسط پارسر عبارت باقاعده نیز پذیرفته میشوند:
\a \b \f \n \N \r \t \u \U \v \x \\
(توجه داشته باشید که \b برای نمایش مرزهای واژه به کار میرود و تنها در کلاسهای نویسه بهمعنای «پسبر» (backspace) است.)
دنبالههای خنثیسازی '\u'، '\U' و '\N' فقط در الگوهای یونیکد (str) شناسایی میشوند. در الگوهای bytes، این موارد خطا محسوب میشوند. دنبالههای خنثیسازی ناشناختهی حروف ASCII برای استفادهی آینده محفوظ هستند و بهعنوان خطا در نظر گرفته میشوند.
خنثیسازیهای مبنای هشت بهصورت محدودی گنجانده شدهاند. اگر اولین رقم 0 باشد یا سه رقم مبنای هشت وجود داشته باشد، بهعنوان یک خنثیسازی مبنای هشت در نظر گرفته میشود. در غیر این صورت، یک ارجاع به گروه است. مانند رشتههای لفظی، طول خنثیسازیهای مبنای هشت همیشه حداکثر سه رقم است.
تغییر یافته در نسخهی 3.3: دنبالههای خنثیسازی '\u' و '\U' افزوده شدهاند.
تغییر یافته در نسخهی 3.6: خنثیسازیهای ناشناختهای که از '\' و یک حرف ASCII تشکیل شدهاند، اکنون خطا محسوب میشوند.
تغییر یافته در نسخهی 3.8: دنباله خنثیسازی '\N{name}' افزوده شده است. همانند مقادیر لفظی رشته، این دنباله به نویسه یونیکد با نام مشخص بسط مییابد (برای مثال '\N{EM DASH}').
این ماژول چندین تابع، چند ثابت و یک استثنا را تعریف میکند. برخی از توابع، نسخههای سادهشدهای از متدهای دارای امکانات کامل برای عبارات باقاعدهی کامپایلشده هستند. بیشتر برنامههای غیربدیهی همیشه از شکل کامپایلشده استفاده میکنند.
تغییر یافته در نسخهی 3.6: ثابتهای پرچمی اکنون نمونههایی از RegexFlag هستند که زیرکلاسی از enum.IntFlag است.
یک کلاس enum.IntFlag که شامل گزینههای regex فهرستشده در زیر است.
اضافه شده در نسخهی 3.11: - added to __all__
باعث میشود \w، \W، \b، \B، \d، \D، \s و \S بهجای تطبیق کامل یونیکد، تطبیق فقط ASCII را انجام دهند. این موضوع فقط برای الگوهای یونیکد (str) معنادار است و برای الگوهای bytes نادیده گرفته میشود.
معادل پرچم درونخطی (?a) است.
نمایش اطلاعات اشکالزدایی درباره عبارت کامپایلشده.
پرچم درونخطی متناظری وجود ندارد.
تطبیق بدون حساسیت به بزرگی و کوچکی حروف را انجام میدهد؛ عبارتهایی مانند [A-Z] با حروف کوچک نیز تطبیق میکنند. تطبیق کامل یونیکد (مانند تطبیق Ü با ü) نیز عمل میکند، مگر اینکه از پرچم ASCII برای غیرفعال کردن تطبیقهای غیر ASCII استفاده شود. تنظیمات locale فعلی تأثیر این پرچم را تغییر نمیدهد، مگر اینکه از پرچم LOCALE نیز استفاده شود.
معادل پرچم درونخطی (?i) است.
توجه داشته باشید که هنگامی که الگوهای یونیکد [a-z] یا [A-Z] بههمراه پرچم IGNORECASE استفاده شوند، با ۵۲ حرف ASCII و ۴ حرف غیرASCII دیگر مطابقت خواهند داشت: 'İ' (U+0130، حرف بزرگ لاتین I با نقطه بالا)، 'ı' (U+0131، حرف کوچک لاتین i بدون نقطه)، 'ſ' (U+017F، حرف کوچک لاتین s بلند) و 'K' (U+212A، نماد کلوین). اگر پرچم ASCII استفاده شود، فقط با حروف 'a' تا 'z' و 'A' تا 'Z' مطابقت داده خواهد شد.
\w، \W، \b، \B و تطبیق بدون حساسیت به بزرگی و کوچکی حروف را به تنظیمات locale وابسته میکند. این پرچم را فقط میتوان با الگوهای بایتی به کار برد.
معادل پرچم درونخطی (?L) است.
هشدار
استفاده از این پرچم توصیه نمیشود؛ در عوض تطبیق یونیکد را در نظر بگیرید. سازوکار تنظیمات locale بسیار غیرقابلاعتماد است، زیرا تنها یک «فرهنگ» را در هر زمان مدیریت میکند و فقط با تنظیمات locale ۸ بیتی کار میکند. تطبیق یونیکد برای الگوهای یونیکد (str) بهطور پیشفرض فعال است و میتواند تنظیمات locale و زبانهای مختلف را مدیریت کند.
تغییر یافته در نسخهی 3.7: اشیای عبارت باقاعدهی کامپایلشده با پرچم LOCALE دیگر به تنظیمات locale در زمان کامپایل وابسته نیستند. تنها تنظیمات locale در زمان تطبیق بر نتیجهی تطبیق تأثیر میگذارد.
هنگامی که تعیین شود، نویسهی الگو '^' در ابتدای رشته و در ابتدای هر خط (بلافاصله پس از هر نویسهی خط جدید) تطابق دارد؛ و نویسهی الگو '$' در انتهای رشته و در انتهای هر خط (بلافاصله پیش از هر نویسهی خط جدید) تطابق دارد. بهطور پیشفرض، '^' فقط در ابتدای رشته تطابق دارد، و '$' فقط در انتهای رشته و بلافاصله پیش از نویسهی خط جدید (در صورت وجود) در انتهای رشته تطابق دارد.
معادل پرچم درونخطی (?m) است.
نشان میدهد که هیچ پرچمی اعمالنشده است؛ مقدار آن 0 است. این پرچم میتواند بهعنوان مقدار پیشفرض برای یک آرگومان کلیدواژهای تابع یا بهعنوان مقدار پایهای که بهصورت شرطی با پرچمهای دیگر OR میشود، استفاده شود. نمونهای از استفاده بهعنوان مقدار پیشفرض:
def myfunc(pattern, text, flag=re.NOFLAG): return re.search(pattern, text, flag)
اضافه شده در نسخهی 3.11.
باعث میشود نویسه ویژه '.' با هر نویسهای، از جمله خط جدید، مطابقت کند؛ بدون این پرچم، '.' با هر چیزی بهجز خط جدید مطابقت میکند.
متناظر با پرچم درونخطی (?s) است.
در Python 3، نویسههای یونیکد بهطور پیشفرض برای الگوهای str تطبیق داده میشوند. بنابراین این پرچم بیمورد و بدون اثر است و فقط برای سازگاری با نسخههای پیشین نگه داشته شده است.
برای محدود کردن تطبیق به نویسههای ASCII، بهجای آن ASCII را ببینید.
این پرچم به شما امکان میدهد عبارتهای باقاعدهای بنویسید که زیباتر به نظر میرسند و خواناتر هستند؛ زیرا میتوانید بخشهای منطقی الگو را بهصورت بصری از هم جدا کنید و توضیح اضافه کنید. فضای سفید درون الگو نادیده گرفته میشود، مگر وقتی در یک کلاس نویسه باشد، یا وقتی یک بکاسلش خنثینشده پیش از آن آمده باشد، یا درون توکنهایی مانند *?، (?: یا (?P<...>. برای مثال، (? : و * ? مجاز نیستند. وقتی سطری شامل # باشد که در یک کلاس نویسه نباشد و یک بکاسلش خنثینشده پیش از آن نیامده باشد، تمام نویسهها از چپترین # با این شرایط تا پایان خط نادیده گرفته میشوند.
این بدان معناست که دو شیء عبارت باقاعده زیر که با یک عدد دهدهی مطابقت دارند، از نظر عملکردی برابرند:
a = re.compile(r"""\d + # the integral part \. # the decimal point \d * # some fractional digits""", re.X) b = re.compile(r"\d+\.\d*")
متناظر با پرچم درونخطی (?x) است.
یک الگوی عبارت باقاعده را به یک شیء عبارت باقاعده کامپایل میکند که میتوان از آن برای تطبیق با استفاده از prefixmatch()، search() و سایر متدهای آن، که در ادامه توصیف شدهاند، استفاده کرد.
رفتار عبارت را میتوان با تعیین یک مقدار flags تغییر داد. مقادیر میتوانند هر یک از متغیرهای flags باشند و با استفاده از OR بیتی (عملگر |) ترکیب شوند.
دنباله
prog = re.compile(pattern) result = prog.search(string)
معادل است با
result = re.search(pattern, string)
اما استفاده از re.compile() و ذخیرهی شیء عبارت باقاعدهی حاصل برای استفادهی مجدد، زمانی که عبارت چندین بار در یک برنامه واحد استفاده شود، کارآمدتر است.
نکته
نسخههای کامپایلشدهی آخرین الگوهای دادهشده به re.compile() و به توابع تطبیق در سطح ماژول، در نهانگاه ذخیره میشوند؛ بنابراین برنامههایی که در هر زمان تنها از چند عبارت باقاعده استفاده میکنند، نیازی به نگرانی دربارهی کامپایل کردن عبارات باقاعده ندارند.
string را پیمایش میکند تا نخستین مکانی را بیابد که عبارت باقاعدهی pattern در آن تطابقی ایجاد میکند، و یک Match متناظر برمیگرداند. اگر هیچ موقعیتی در رشته با الگو تطابق نداشته باشد، None برمیگرداند؛ توجه داشته باشید که این با یافتن یک تطابق به طول صفر در نقطهای از رشته متفاوت است.
رفتار عبارت را میتوان با تعیین یک مقدار flags تغییر داد. مقادیر میتوانند هر یک از متغیرهای flags باشند و با استفاده از OR بیتی (عملگر |) ترکیب شوند.
اگر صفر یا چند نویسه در ابتدای string با عبارت باقاعدهی pattern تطابق داشته باشند، یک Match متناظر برمیگرداند. اگر رشته با الگو تطابق نداشته باشد، None برمیگرداند؛ توجه داشته باشید که این با یک تطابق با طول صفر متفاوت است.
نکته
حتی در حالت MULTILINE، این مورد فقط در ابتدای رشته مطابقت پیدا میکند و نه در ابتدای هر سطر.
اگر میخواهید یک تطابق را در هر جای string پیدا کنید، در عوض از search() استفاده کنید (همچنین تابع search() در برابر prefixmatch() را ببینید).
رفتار عبارت را میتوان با تعیین یک مقدار flags تغییر داد. مقادیر میتوانند هر یک از متغیرهای flags باشند و با استفاده از OR بیتی (عملگر |) ترکیب شوند.
این تابع اکنون دو نام دارد و مدتهاست با نام match() شناخته میشود. هنگامی که نیاز دارید سازگاری با نسخههای قدیمیتر پایتون را حفظ کنید، از آن نام استفاده کنید.
اضافه شده در نسخهی 3.15.
منسوخسازی نرم <Soft deprecated> از نسخهی 3.15: تابع match() به نفع نام جایگزین prefixmatch() از این API که توصیف صریحتری دارد، به صورت منسوخ نرم درآمده است. از آن برای بیان بهتر مقصود استفاده کنید. هنجار در سایر زبانها و پیادهسازیهای عبارت باقاعده این است که از اصطلاح match برای ارجاع به رفتاری استفاده شود که پایتون همواره آن را search() نامیده است. نگاه کنید به توابع prefixmatch() در برابر match().
اگر کل string با عبارت باقاعده pattern تطابق داشته باشد، یک Match متناظر برمیگرداند. اگر رشته با الگو تطابق نداشته باشد، None برمیگرداند؛ توجه داشته باشید که این با تطابق با طول صفر متفاوت است.
رفتار عبارت را میتوان با تعیین یک مقدار flags تغییر داد. مقادیر میتوانند هر یک از متغیرهای flags باشند و با استفاده از OR بیتی (عملگر |) ترکیب شوند.
اضافه شده در نسخهی 3.4.
string را بر اساس موارد وقوع pattern تقسیم میکند. اگر در pattern از پرانتزهای ثبتکننده استفاده شود، متن همهی گروههای موجود در الگو نیز بهعنوان بخشی از فهرست حاصل بازگردانده میشود. اگر maxsplit ناصفر باشد، حداکثر maxsplit تقسیم صورت میگیرد و باقیماندهی رشته بهعنوان آخرین عنصر فهرست بازگردانده میشود.
>>> re.split(r'\W+', 'Words, words, words.') ['Words', 'words', 'words', ''] >>> re.split(r'(\W+)', 'Words, words, words.') ['Words', ', ', 'words', ', ', 'words', '.', ''] >>> re.split(r'\W+', 'Words, words, words.', maxsplit=1) ['Words', 'words, words.'] >>> re.split('[a-f]+', '0a3B9', flags=re.IGNORECASE) ['0', '3', '9']
اگر جداکننده دارای گروههای ثبتکننده باشد و در ابتدای رشته تطابق داشته باشد، نتیجه با یک رشته خالی آغاز میشود. همین حالت برای انتهای رشته نیز صادق است:
>>> re.split(r'(\W+)', '...words, words...') ['', '...', 'words', ', ', 'words', '...', '']
به این ترتیب، کامپوننتهای جداکننده همیشه در اندیسهای نسبی یکسان در فهرست نتیجه یافت میشوند.
امکان تطابقهای خالی مجاور وجود ندارد، اما یک تطابق خالی میتواند بلافاصله پس از یک تطابق غیرخالی رخ دهد.
>>> re.split(r'\b', 'Words, words, words.') ['', 'Words', ', ', 'words', ', ', 'words', '.'] >>> re.split(r'\W*', '...words...') ['', '', 'w', 'o', 'r', 'd', 's', '', ''] >>> re.split(r'(\W*)', '...words...') ['', '...', '', '', 'w', '', 'o', '', 'r', '', 'd', '', 's', '...', '', '', '']
رفتار عبارت را میتوان با تعیین یک مقدار flags تغییر داد. مقادیر میتوانند هر یک از متغیرهای flags باشند و با استفاده از OR بیتی (عملگر |) ترکیب شوند.
تغییر یافته در نسخهی 3.1: آرگومان اختیاری flags افزوده شد.
تغییر یافته در نسخهی 3.7: پشتیبانی از جداسازی بر اساس الگویی که میتواند با رشته خالی مطابقت داشته باشد، اضافه شد.
منسوخ شده از نسخهی 3.13: ارسال maxsplit و flags بهعنوان آرگومانهای جایگاهی منسوخ شده است. در نسخههای آینده پایتون، آنها پارامترهای فقط کلیدواژهای خواهند بود.
تمام تطابقهای غیرهمپوشانِ pattern در string را بهصورت فهرستی از رشتهها یا تاپلها برمیگرداند. string از چپ به راست پیمایش میشود و تطابقها به ترتیبی که یافت میشوند، برگردانده میشوند. تطابقهای خالی نیز در نتیجه گنجانده میشوند.
نتیجه به تعداد گروههای ثبتکننده در الگو بستگی دارد. اگر هیچ گروهی وجود نداشته باشد، فهرستی از رشتههای منطبق با کل الگو برمیگرداند. اگر دقیقاً یک گروه وجود داشته باشد، فهرستی از رشتههای منطبق با آن گروه برمیگرداند. اگر چندین گروه وجود داشته باشد، فهرستی از تاپلهایی از رشتههای منطبق با گروهها برمیگرداند. گروههای غیرثبتکننده بر شکل نتیجه تأثیری ندارند.
>>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest') ['foot', 'fell', 'fastest'] >>> re.findall(r'(\w+)=(\d+)', 'set width=20 and height=10') [('width', '20'), ('height', '10')]
رفتار عبارت را میتوان با تعیین یک مقدار flags تغییر داد. مقادیر میتوانند هر یک از متغیرهای flags باشند و با استفاده از OR بیتی (عملگر |) ترکیب شوند.
تغییر یافته در نسخهی 3.7: تطابقهای غیرخالی اکنون میتوانند درست پس از یک تطابق خالی پیشین آغاز شوند.
یک iterator برگردانید که روی همهی تطبیقهای غیرهمپوشان الگوی عبارت باقاعدهی pattern در string، شیءهای Match را تولید میکند. string از چپ به راست پیمایش میشود و تطبیقها به ترتیبی که پیدا میشوند برگردانده میشوند. تطبیقهای خالی نیز در نتیجه گنجانده میشوند.
رفتار عبارت را میتوان با تعیین یک مقدار flags تغییر داد. مقادیر میتوانند هر یک از متغیرهای flags باشند و با استفاده از OR بیتی (عملگر |) ترکیب شوند.
تغییر یافته در نسخهی 3.7: تطابقهای غیرخالی اکنون میتوانند درست پس از یک تطابق خالی پیشین آغاز شوند.
رشتهی حاصل از جایگزینی چپترین رخدادهای بدون همپوشانی pattern در string با جایگزین repl را برمیگرداند. اگر pattern یافت نشود، string بدون تغییر برگردانده میشود. repl میتواند یک رشته یا یک تابع باشد؛ اگر رشته باشد، هرگونه دنبالهی خنثیسازی با بکاسلش در آن پردازش میشود. یعنی \n به یک نویسهی خط جدید تبدیل میشود، \r به بازگشت به ابتدای سطر تبدیل میشود، و به همین ترتیب. دنبالههای خنثیسازی ناشناختهی شامل حروف ASCII برای استفادهی آینده محفوظ هستند و بهعنوان خطا تلقی میشوند. سایر دنبالههای خنثیسازی ناشناخته مانند \& بهحال خود باقی میمانند. بازارجاعها (backreferences)، مانند \6، با زیررشتهای که گروه ۶ در الگو آن را تطبیق داده است، جایگزین میشوند. برای مثال:
>>> re.sub(r'def\s+([a-zA-Z_][a-zA-Z_0-9]*)\s*\(\s*\):', ... r'static PyObject*\npy_\1(void)\n{', ... 'def myfunc():') 'static PyObject*\npy_myfunc(void)\n{'
اگر repl یک تابع باشد، برای هر رخداد غیرهمپوشان pattern فراخوانی میشود. این تابع یک آرگومان از نوع Match میگیرد و رشته جایگزینی را برمیگرداند. برای مثال:
>>> def dashrepl(matchobj): ... if matchobj.group(0) == '-': return ' ' ... else: return '-' ... >>> re.sub('-{1,2}', dashrepl, 'pro----gram-files') 'pro--gram files' >>> re.sub(r'\sAND\s', ' & ', 'Baked Beans And Spam', flags=re.IGNORECASE) 'Baked Beans & Spam'
الگو ممکن است یک رشته یا یک Pattern باشد.
آرگومان اختیاری count حداکثر تعداد رخدادهای الگو برای جایگزینی است؛ count باید یک عدد صحیح غیرمنفی باشد. اگر حذف شود یا صفر باشد، تمام رخدادهای الگو جایگزین میشوند.
تطبیقهای خالی مجاور امکانپذیر نیستند، اما یک تطبیق خالی میتواند بلافاصله پس از یک تطبیق غیرخالی رخ دهد. در نتیجه، sub('x*', '-', 'abxd') مقدار '-a-b--d-' را بهجای '-a-b-d-' برمیگرداند.
در آرگومانهای repl از نوع رشته، علاوه بر دنبالههای خنثیسازی نویسه و بازارجاعها شرحدادهشده در بالا، \g<name> از زیررشتهی تطبیقدادهشده با گروهی به نام name استفاده خواهد کرد، همانطور که با سینتکس (?P<name>...) تعریف شده است. \g<number> از شمارهی گروه متناظر استفاده میکند؛ بنابراین \g<2> معادل \2 است، اما در جایگزینی مانند \g<2>0 مبهم نیست. \20 بهعنوان ارجاعی به گروه ۲۰ تفسیر میشود، نه ارجاعی به گروه ۲ که پس از آن نویسهی لفظی '0' آمده است. بازارجاع \g<0> با کل زیررشتهی تطبیقدادهشده با RE جایگزین میشود.
رفتار عبارت را میتوان با تعیین یک مقدار flags تغییر داد. مقادیر میتوانند هر یک از متغیرهای flags باشند و با استفاده از OR بیتی (عملگر |) ترکیب شوند.
تغییر یافته در نسخهی 3.1: آرگومان اختیاری flags افزوده شد.
تغییر یافته در نسخهی 3.5: گروههای مطابقتنشده با یک رشته خالی جایگزین میشوند.
تغییر یافته در نسخهی 3.6: خنثیسازیهای ناشناخته در pattern که از '\' و یک حرف ASCII تشکیل شدهاند، اکنون خطا محسوب میشوند.
تغییر یافته در نسخهی 3.7: دنبالههای خنثیسازی ناشناخته در repl که از '\' و یک حرف ASCII تشکیل شدهاند، اکنون خطا هستند. یک تطابق خالی میتواند بلافاصله پس از یک تطابق غیرخالی رخ دهد.
تغییر یافته در نسخهی 3.12: شناسهی گروه id فقط میتواند شامل ارقام ASCII باشد. در رشتههای جایگزینی bytes، نام گروه name فقط میتواند شامل بایتهایی در محدودهی ASCII باشد (b'\x00'-b'\x7f').
منسوخ شده از نسخهی 3.13: ارسال count و flags بهعنوان آرگومانهای جایگاهی منسوخ شده است. در نسخههای آینده پایتون، آنها پارامترهای فقط کلیدواژهای خواهند بود.
همان عملیات sub() را انجام میدهد، اما یک تاپل به شکل (new_string, number_of_subs_made) برمیگرداند.
رفتار عبارت را میتوان با تعیین یک مقدار flags تغییر داد. مقادیر میتوانند هر یک از متغیرهای flags باشند و با استفاده از OR بیتی (عملگر |) ترکیب شوند.
نویسههای خاص در pattern را خنثی کنید. این کار زمانی مفید است که بخواهید یک رشتهی لفظی دلخواه را تطبیق دهید که ممکن است حاوی نویسههای ویژهی عبارت باقاعده باشد. برای نمونه:
>>> print(re.escape('https://www.python.org')) https://www\.python\.org >>> legal_chars = string.ascii_lowercase + string.digits + "!#$%&'*+-.^_`|~:" >>> print('[%s]+' % re.escape(legal_chars)) [abcdefghijklmnopqrstuvwxyz0123456789!\#\$%\&'\*\+\-\.\^_`\|\~:]+ >>> operators = ['+', '-', '*', '/', '**'] >>> print('|'.join(map(re.escape, sorted(operators, reverse=True)))) /|\-|\+|\*\*|\*
از این تابع نباید برای رشته جایگزین در sub() و subn() استفاده شود، فقط بکاسلشها باید خنثی شوند. برای مثال:
>>> digits_re = r'\d+' >>> sample = '/usr/sbin/sendmail - 0 errors, 12 warnings' >>> print(re.sub(digits_re, digits_re.replace('\\', r'\\'), sample)) /usr/sbin/sendmail - \d+ errors, \d+ warnings
تغییر یافته در نسخهی 3.3: نویسهی '_' دیگر خنثی نمیشود.
تغییر یافته در نسخهی 3.7: تنها نویسههایی که میتوانند در یک عبارت باقاعده معنای خاصی داشته باشند، خنثی میشوند. در نتیجه، '!'، '"'، '%'، "'"، ','، '/'، ':'، ';'، '<'، '='، '>'، '@' و "`" دیگر خنثی نمیشوند.
نهانگاه عبارت باقاعده را پاک میکند.
استثنایی که هنگامی پرتاب میشود که رشتهای به یکی از توابع اینجا داده شود و یک عبارت باقاعده معتبر نباشد (برای مثال، ممکن است شامل پرانتزهای جفتنشده باشد) یا زمانی که خطای دیگری در حین کامپایل یا تطبیق رخ دهد. اگر رشتهای هیچ تطبیقی برای یک الگو نداشته باشد، هرگز خطا محسوب نمیشود. نمونه PatternError دارای ویژگیهای اضافی زیر است:
پیام خطای قالببندینشده.
الگوی عبارت باقاعده.
اندیسی در pattern که کامپایل در آن ناموفق بود (ممکن است None باشد).
سطر متناظر با pos (ممکن است None باشد).
ستون متناظر با pos (ممکن است None باشد).
تغییر یافته در نسخهی 3.5: ویژگیهای بیشتری اضافه شد.
تغییر یافته در نسخهی 3.13: PatternError در ابتدا با نام error نامگذاری شده بود؛ این نام برای سازگاری با نسخههای پیشین بهعنوان یک نام مستعار حفظ شده است.
شیء عبارت باقاعدهی کامپایلشده که توسط re.compile() بازگردانده میشود.
الگوها نسبت به نوع رشتهای که پردازش میکنند (str یا bytes) عام هستند.
تغییر یافته در نسخهی 3.9: re.Pattern از [] برای مشخص کردن یک الگوی یونیکد (str) یا بایتی پشتیبانی میکند. نوع نام مستعار عام را ببینید.
string را پیمایش میکند تا نخستین مکانی را پیدا کند که این عبارت باقاعده در آن یک تطابق ایجاد میکند، و یک Match متناظر برمیگرداند. اگر هیچ موقعیتی در رشته با الگو تطابق نداشته باشد، None برمیگرداند؛ توجه داشته باشید که این با یافتن یک تطابق با طول صفر در نقطهای از رشته متفاوت است.
پارامتر اختیاری دوم pos، اندیسی در رشته را مشخص میکند که جستجو باید از آن آغاز شود؛ مقدار پیشفرض آن 0 است. این بهطور کامل معادل اسلایس رشته نیست؛ نویسهی الگوی '^' در آغاز واقعی رشته و در موقعیتهای درست پس از یک خط جدید تطابق دارد، اما نه لزوماً در اندیسی که جستجو باید از آن آغاز شود.
پارامتر اختیاری endpos میزان جستجو در رشته را محدود میکند؛ بهطوری که گویی رشته endpos نویسه طول دارد، بنابراین فقط نویسهها از pos تا endpos - 1 برای تطابق جستجو میشوند. اگر endpos کمتر از pos باشد، هیچ تطابقی یافت نخواهد شد؛ در غیر این صورت، اگر rx یک شیء عبارت باقاعده کامپایلشده باشد، rx.search(string, 0, 50) معادل rx.search(string[:50], 0) است.
>>> pattern = re.compile("d") >>> pattern.search("dog") # Match at index 0 <re.Match object; span=(0, 1), match='d'> >>> pattern.search("dog", 1) # No match; search doesn't include the "d"
اگر این عبارت باقاعده با صفر یا چند نویسه در ابتدای رشته تطابق داشته باشد، یک Match متناظر برمیگرداند. اگر رشته با الگو تطابق نداشته باشد، None برمیگرداند؛ توجه داشته باشید که این با یک تطابق با طول صفر متفاوت است.
توجه داشته باشید که حتی در حالت MULTILINE، این مورد فقط در ابتدای رشته مطابقت پیدا میکند و نه در ابتدای هر سطر.
پارامترهای اختیاری pos و endpos همان معنایی را دارند که برای متد search() دارند.
>>> pattern = re.compile("o") >>> pattern.prefixmatch("dog") # No match as "o" is not at the start of "dog". >>> pattern.prefixmatch("dog", 1) # Match as "o" is the 2nd character of "dog". <re.Match object; span=(1, 2), match='o'>
اگر میخواهید تطابقی را در هر جای string بیابید، در عوض از search() استفاده کنید (همچنین تابع search() در برابر prefixmatch() را ببینید).
این متد اکنون دو نام دارد و مدتهاست با نام match() شناخته میشود. هنگامی که نیاز دارید سازگاری با نسخههای قدیمیتر پایتون را حفظ کنید، از آن نام استفاده کنید.
اضافه شده در نسخهی 3.15.
منسوخسازی نرم <Soft deprecated> از نسخهی 3.15: متد match() به نفع نام جایگزین prefixmatch() از این API که توصیف صریحتری دارد، به صورت منسوخ نرم درآمده است. از آن برای بیان بهتر مقصود استفاده کنید. هنجار در سایر زبانها و پیادهسازیهای عبارت باقاعده این است که از اصطلاح match برای ارجاع به رفتاری استفاده شود که پایتون همواره آن را search() نامیده است. نگاه کنید به توابع prefixmatch() در برابر match().
اگر کل رشته با این عبارت باقاعده تطابق داشته باشد، یک Match متناظر برمیگرداند. اگر رشته با الگو تطابق نداشته باشد، None برمیگرداند؛ توجه داشته باشید که این با یک تطابق با طول صفر متفاوت است.
پارامترهای اختیاری pos و endpos همان معنایی را دارند که برای متد search() دارند.
>>> pattern = re.compile("o[gh]") >>> pattern.fullmatch("dog") # No match as "o" is not at the start of "dog". >>> pattern.fullmatch("ogre") # No match as not the full string matches. >>> pattern.fullmatch("doggie", 1, 3) # Matches within given limits. <re.Match object; span=(1, 3), match='og'>
اضافه شده در نسخهی 3.4.
مشابه تابع findall() است و از الگوی کامپایلشده استفاده میکند، اما پارامترهای اختیاری pos و endpos را نیز میپذیرد که ناحیهی جستجو را مانند search() محدود میکنند.
مشابه تابع finditer()، از الگوی کامپایلشده استفاده میکند، اما پارامترهای اختیاری pos و endpos را نیز میپذیرد که ناحیه جستجو را مانند search() محدود میکنند.
پرچمهای تطبیق عبارت باقاعده. این ترکیبی است از پرچمهای دادهشده به compile()، هر پرچم درونخطی (?...) در الگو، و پرچمهای ضمنی مانند UNICODE در صورتی که الگو یک رشته یونیکد باشد.
تعداد گروههای ثبتکننده (capturing groups) در الگو.
یک دیکشنری که هر یک از نامهای گروه نمادین تعریفشده با (?P<id>) را به شمارههای گروه نگاشت میکند. اگر در الگو از هیچ گروه نمادینی استفاده نشده باشد، دیکشنری خالی است.
رشتهی الگویی که شیء الگو از آن کامپایلشده است.
تغییر یافته در نسخهی 3.7: پشتیبانی از copy.copy() و copy.deepcopy() افزوده شد. اشیای عبارت باقاعدهی کامپایلشده، اتمی در نظر گرفته میشوند.
اشیای Match همیشه مقدار بولی True دارند. از آنجا که match() و search() وقتی هیچ تطبیقی وجود نداشته باشد None برمیگردانند، میتوانید با یک دستور if ساده بررسی کنید که آیا تطبیقی وجود داشته است:
if match := re.search(pattern, string): process(match)
شیء Match برگرداندهشده توسط فراخوانیهای موفق match و search.
تطبیقها نسبت به نوع رشتهای که تطبیق داده شده است عام هستند (str یا bytes).
تغییر یافته در نسخهی 3.9: re.Match از [] برای مشخص کردن تطبیق یونیکد (str) یا بایت پشتیبانی میکند. نوع نام مستعار عام را ببینید.
رشتهای را برمیگرداند که با انجام جایگزینی بکاسلش روی رشتهی الگو template به دست میآید، همانطور که توسط متد sub() انجام میشود. دنبالههای خنثیسازی مانند \n به نویسههای مناسب تبدیل میشوند، و بازارجاعهای عددی (\1، \2) و بازارجاعهای نامدار (\g<1>، \g<name>) با محتوای گروه متناظر جایگزین میشوند. بازارجاع \g<0> با کل تطبیق جایگزین خواهد شد.
تغییر یافته در نسخهی 3.5: گروههای مطابقتنشده با یک رشته خالی جایگزین میشوند.
یک یا چند زیرگروه از تطابق را برمیگرداند. اگر تنها یک آرگومان وجود داشته باشد، نتیجه یک رشتهی تنها است؛ اگر چند آرگومان وجود داشته باشد، نتیجه یک تاپل با یک آیتم بهازای هر آرگومان است. بدون آرگومان، group1 بهطور پیشفرض ۰ است (کل تطابق برگردانده میشود). اگر آرگومان groupN برابر ۰ باشد، مقدار بازگشتی متناظر، کل رشتهی مطابقشده است؛ اگر یک عدد صحیح مثبت باشد، رشتهای است که با گروه پرانتزدار متناظر مطابقت دارد. اگر شمارهی گروه منفی یا بزرگتر از تعداد گروههای تعریفشده در الگو باشد، استثنای IndexError پرتاب میشود. اگر گروهی در بخشی از الگو قرار داشته باشد که تطابق نداشته است، نتیجهی متناظر None است. اگر گروهی در بخشی از الگو قرار داشته باشد که چند بار تطابق یافته است، آخرین تطابق برگردانده میشود.
>>> m = re.search(r"\A(\w+) (\w+)", "Norwegian Blue, pining for the fjords") >>> m.group(0) # تمام تطابق 'Norwegian Blue' >>> m.group(1) # اولین زیرگروه پرانتزدار. 'Norwegian' >>> m.group(2) # دومین زیرگروه پرانتزدار. 'Blue' >>> m.group(1, 2) # چندین آرگومان یک تاپل به ما میدهند. ('Norwegian', 'Blue')
اگر عبارت باقاعده از سینتکس (?P<name>...) استفاده کند، آرگومانهای groupN همچنین میتوانند رشتههایی باشند که گروهها را با نام گروه آنها شناسایی میکنند. اگر یک آرگومان رشتهای بهعنوان نام گروه در الگو استفاده نشود، یک استثنای IndexError پرتاب میشود.
یک مثال نسبتاً پیچیده:
>>> m = re.search(r"(?P<adjective>\w+) (?P<animal>\w+)", "killer rabbit") >>> m.group('adjective') 'killer' >>> m.group('animal') 'rabbit'
همچنین میتوان به گروههای نامدار از طریق اندیس آنها ارجاع داد:
>>> m.group(1) 'killer' >>> m.group(2) 'rabbit'
اگر یک گروه چندین بار تطابق داشته باشد، تنها آخرین تطابق قابل دسترسی است:
>>> m = re.search(r"(..)+", "a1b2c3") # ۳ بار تطابق پیدا میکند. >>> m.group(1) # فقط آخرین تطابق را برمیگرداند. 'c3'
این دقیقاً معادل m.group(g) است. این کار دسترسی به یک گروه منفرد از یک تطبیق را آسانتر میکند:
>>> m = re.search(r"(\w+) (\w+)", "Norwegian Blue, pining for the fjords") >>> m[0] # تمام تطابق 'Norwegian Blue' >>> m[1] # اولین زیرگروه پرانتزدار. 'Norwegian' >>> m[2] # دومین زیرگروه پرانتزدار. 'Blue'
گروههای نامگذاریشده نیز پشتیبانی میشوند:
>>> m = re.search(r"(?P<adjective>\w+) (?P<animal>\w+)", "killer rabbit") >>> m['adjective'] 'killer' >>> m['animal'] 'rabbit'
اضافه شده در نسخهی 3.6.
یک تاپل حاوی تمام زیرگروههای تطابق، از ۱ تا هر تعداد گروهی که در الگو وجود دارد، برمیگرداند. آرگومان default برای گروههایی استفاده میشود که در تطابق شرکت نکردهاند؛ مقدار پیشفرض آن None است.
برای مثال:
>>> m = re.search(r"(\d+)\.(\d+)", "24.1632") >>> m.groups() ('24', '1632')
اگر نقطه اعشار و همه چیز پس از آن را اختیاری کنیم، ممکن است همه گروهها در تطبیق شرکت نکنند. مقدار پیشفرض این گروهها None خواهد بود، مگر اینکه آرگومان default داده شده باشد:
>>> m = re.search(r"(\d+)\.?(\d+)?", "24") >>> m.groups() # گروه دوم به طور پیشفرض None است. ('24', None) >>> m.groups('0') # اکنون، گروه دوم به طور پیشفرض '0' است. ('24', '0')
یک دیکشنری شامل تمام زیرگروههای نامدار تطبیق برمیگرداند که کلیدهای آن نام زیرگروهها هستند. آرگومان default برای گروههایی استفاده میشود که در تطبیق شرکت نکردهاند؛ مقدار پیشفرض آن None است. برای مثال:
>>> m = re.search(r"(?P<adjective>\w+) (?P<animal>\w+)", "killer rabbit") >>> m.groupdict() {'adjective': 'killer', 'animal': 'rabbit'}
اندیسهای آغاز و پایان زیررشتهی تطبیقیافته با group را برمیگرداند؛ group بهطور پیشفرض ۰ است (به معنای کل زیررشتهی تطبیقیافته). اگر group وجود داشته باشد اما در تطبیق مشارکت نکرده باشد، -1 را برمیگرداند. برای یک شیء تطبیق m، و گروه g که در تطبیق مشارکت داشته باشد، زیررشتهی تطبیقیافته با گروه g (معادل m.group(g)) عبارت است از
m.string[m.start(g):m.end(g)]
توجه داشته باشید که اگر group با یک رشته خالی تطابق داشته باشد، m.start(group) با m.end(group) برابر خواهد بود. برای مثال، پس از m = re.search('b(c?)', 'cba')، m.start(0) برابر ۱ است، m.end(0) برابر ۲ است، m.start(1) و m.end(1) هر دو ۲ هستند و m.start(2) استثنای IndexError را پرتاب میکند.
مثالی که remove_this را از نشانیهای ایمیل حذف میکند:
>>> email = "tony@tiremove_thisger.net" >>> m = re.search("remove_this", email) >>> email[:m.start()] + email[m.end():] '[email protected]'
برای یک تطابق m، تاپل دوتایی (m.start(group), m.end(group)) را برمیگرداند. توجه داشته باشید که اگر group در تطابق مشارکت نداشته باشد، این مقدار (-1, -1) خواهد بود. group بهطور پیشفرض صفر است، یعنی کل تطابق.
مقدار pos که به متد search() یا match() یک شیء regex ارسال شده است. این اندیسی در رشته است که موتور RE جستوجو برای یک تطابق را از آن آغاز کرده است.
مقدار endpos که به متد search() یا match() یک شیء regex ارسال شده است. این اندیسی در رشته است که موتور RE از آن فراتر نخواهد رفت.
اندیس عدد صحیح برای آخرین گروه ثبتکننده تطبیقیافته، یا None اگر اصلاً هیچ گروهی تطبیق نیافته باشد. برای مثال، عبارتهای (a)b، ((a)(b)) و ((ab)) اگر روی رشته 'ab' اعمال شوند، دارای lastindex == 1 خواهند بود، در حالی که عبارت (a)(b) اگر روی همان رشته اعمال شود، دارای lastindex == 2 خواهد بود.
نام آخرین گروه ثبتکننده (capturing group) تطبیقیافته، یا None اگر آن گروه نامی نداشته باشد، یا اگر اصلاً هیچ گروهی تطبیق داده نشده باشد.
شیء عبارت باقاعده که متد match() یا search() آن، این نمونهی تطبیق را تولید کرده است.
تغییر یافته در نسخهی 3.7: پشتیبانی از copy.copy() و copy.deepcopy() افزوده شد. اشیای Match اتمی در نظر گرفته میشوند.
در این مثال، از تابع کمکی زیر استفاده میکنیم تا اشیای تطبیق (match objects) را کمی مناسبتر نمایش دهیم:
def displaymatch(match): if match is None: return None return '<Match: %r, groups=%r>' % (match.group(), match.groups())
فرض کنید در حال نوشتن یک برنامه پوکر هستید که در آن دست یک بازیکن بهصورت یک رشته ۵ نویسهای نمایش داده میشود و هر نویسه نمایانگر یک کارت است: "a" برای آس، "k" برای شاه، "q" برای بیبی، "j" برای سرباز، "t" برای ۱۰، و "2" تا "9" نمایانگر کارتی با همان مقدار.
برای بررسی اینکه آیا یک رشتهی دادهشده یک دست معتبر است، میتوانید کار زیر را انجام دهید:
>>> valid_hand_re = re.compile(r"^[a2-9tjqk]{5}$") >>> displaymatch(valid_hand_re.search("akt5q")) # معتبر. "<Match: 'akt5q', groups=()>" >>> displaymatch(valid_hand_re.search("akt5e")) # نامعتبر. >>> displaymatch(valid_hand_re.search("akt")) # نامعتبر. >>> displaymatch(valid_hand_re.search("727ak")) # معتبر. "<Match: '727ak', groups=()>"
آن دست آخر، "727ak"، شامل یک جفت، یا دو کارت با ارزش یکسان بود. برای تطبیق این موضوع با یک عبارت باقاعده، میتوان از بازارجاعها (backreferences) به این شکل استفاده کرد:
>>> pair_re = re.compile(r".*(.).*\1") >>> displaymatch(pair_re.prefixmatch("717ak")) # جفت از ۷ها. "<Match: '717', groups=('7',)>" >>> displaymatch(pair_re.prefixmatch("718ak")) # بدون جفت. >>> displaymatch(pair_re.prefixmatch("354aa")) # جفت از آسها. "<Match: '354aa', groups=('a',)>"
برای فهمیدن این که یک جفت از چه کارتی تشکیل شده است، میتوانید از متد group() شیء تطابق به شکل زیر استفاده کنید:
>>> pair_re = re.compile(r".*(.).*\1") >>> pair_re.prefixmatch("717ak").group(1) '7' # خطا به این دلیل که prefixmatch() مقدار None را برمیگرداند که متد group() را ندارد: >>> pair_re.prefixmatch("718ak").group(1) Traceback (most recent call last): File "<pyshell#23>", line 1, in <module> pair_re.prefixmatch("718ak").group(1) AttributeError: 'NoneType' object has no attribute 'group' >>> pair_re.prefixmatch("354aa").group(1) 'a'
پایتون در حال حاضر معادلی برای scanf() ندارد. عبارات باقاعده معمولاً از رشتههای قالب scanf() قدرتمندتر هستند، هرچند پرجزئیاتتر نیز میباشند. جدول زیر چند نگاشت کموبیش معادل میان نشانههای قالب scanf() و عبارات باقاعده ارائه میدهد.
توکن |
عبارت باقاعده |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
برای استخراج نام پرونده و اعداد از یک رشته مانند:
/usr/sbin/sendmail - 0 errors, 4 warnings
میتوانید از قالب scanf() مانند زیر استفاده کنید:
%s - %d errors, %d warnings
عبارت باقاعدهی معادل به شکل زیر خواهد بود:
(\S+) - (\d+) errors, (\d+) warnings
پایتون عملیاتهای اولیهی مختلفی را بر پایهی عبارات باقاعده ارائه میدهد:
re.prefixmatch() وجود تطابق را تنها در ابتدای رشته بررسی میکند
re.search() وجود تطابق در هر جای رشته را بررسی میکند (Perl بهطور پیشفرض همین کار را انجام میدهد).
re.fullmatch() بررسی میکند که کل رشته تطابق داشته باشد
برای مثال:
>>> re.prefixmatch("c", "abcdef") # بدون تطابق >>> re.search("c", "abcdef") # تطابق <re.Match object; span=(2, 3), match='c'> >>> re.fullmatch("p.*n", "python") # تطابق <re.Match object; span=(0, 6), match='python'> >>> re.fullmatch("r.*n", "python") # بدون تطابق
عبارتهای باقاعدهای که با '^' شروع میشوند را میتوان همراه با search() برای محدود کردن تطابق به ابتدای رشته استفاده کرد:
>>> re.prefixmatch("c", "abcdef") # No match >>> re.search("^c", "abcdef") # No match >>> re.search("^a", "abcdef") # Match <re.Match object; span=(0, 1), match='a'>
با این حال، توجه داشته باشید که در حالت MULTILINE تابع prefixmatch() تنها در ابتدای رشته مطابقت پیدا میکند، در حالی که استفاده از search() با یک عبارت باقاعده که با '^' شروع میشود، در ابتدای هر سطر مطابقت خواهد داشت.
>>> re.prefixmatch("X", "A\nB\nX", re.MULTILINE) # No match >>> re.search("^X", "A\nB\nX", re.MULTILINE) # Match <re.Match object; span=(4, 5), match='X'>
چرا تابع و متد match() به نفع املای طولانیتر prefixmatch() توصیه نمیشود؟
از زمانی که عبارات باقاعده به پایتون اضافه شدند، بسیاری از زبانهای دیگر کتابخانههای پشتیبانی از عبارات باقاعده را دریافت کردهاند. با این حال، در محبوبترین آنها، از اصطلاح match در APIهای خود استفاده میکنند تا به رفتار بدون لنگر ارجاع دهند که در پایتون توسط search() فراهم شده است. بنابراین، استفاده از اصطلاح سادهی match ممکن است برای کسانی که به زبانهای دیگر عادت دارند و با واگرایی API پایتون از آنچه به هنجار صنعت تبدیل شده است آشنا نیستند، هنگام خواندن یا نوشتن کد نامفهوم باشد.
به نقل از ذن پایتون (python3 -m this): "صریح بودن بهتر از ضمنی بودن است". هر کسی که نام prefixmatch() را میخواند احتمالاً معناشناسی مورد نظر را درک خواهد کرد. هنگام خواندن match() همچنان بذر تردیدی دربارهی رفتار مورد نظر برای هر کسی که از پیش با این تلهی قدیمی پایتون آشنا نیست، باقی میماند.
ما قصد نداریم نام قدیمیتر match() را حذف کنیم، زیرا بیش از ۳۰ سال است که در کد استفاده میشود. این نام به صورت منسوخ نرم درآمده است: کدهایی که از نسخههای قدیمیتر پایتون پشتیبانی میکنند باید به استفاده از match() ادامه دهند، در حالی که کدهای جدید باید prefixmatch() را ترجیح دهند.
اضافه شده در نسخهی 3.15: prefixmatch()
منسوخسازی نرم <Soft deprecated> از نسخهی 3.15: match()
split() یک رشته را به فهرستی جداشده با الگوی دادهشده تقسیم میکند. این متد برای تبدیل دادههای متنی به ساختارهای دادهای که بهراحتی توسط پایتون قابل خواندن و اصلاح هستند، بسیار ارزشمند است؛ همانطور که در مثال زیر که یک دفترچه تلفن ایجاد میکند، نشان داده شده است.
ابتدا، ورودی در اینجا آمده است. معمولاً ممکن است از یک پرونده آمده باشد، در اینجا از سینتکس رشته سهنقلقولی استفاده میکنیم
>>> text = """Ross McFluff: 834.345.1254 155 Elm Street ... ... Ronald Heathmore: 892.345.3428 436 Finley Avenue ... Frank Burger: 925.541.7625 662 South Dogwood Way ... ... ... Heather Albrecht: 548.326.4584 919 Park Place"""
مدخلها با یک یا چند سطر جدید از هم جدا شدهاند. اکنون رشته را به فهرستی تبدیل میکنیم که در آن هر خط غیرخالی مدخل جداگانهی خود را دارد:
>>> entries = re.split("\n+", text) >>> entries ['Ross McFluff: 834.345.1254 155 Elm Street', 'Ronald Heathmore: 892.345.3428 436 Finley Avenue', 'Frank Burger: 925.541.7625 662 South Dogwood Way', 'Heather Albrecht: 548.326.4584 919 Park Place']
در نهایت، هر ورودی را به فهرستی شامل نام، نام خانوادگی، شماره تلفن و نشانی تفکیک کنید. ما از پارامتر maxsplit در split() استفاده میکنیم، زیرا نشانی حاوی فاصلهها، یعنی الگوی تفکیک ما، است:
>>> [re.split(":? ", entry, maxsplit=3) for entry in entries] [['Ross', 'McFluff', '834.345.1254', '155 Elm Street'], ['Ronald', 'Heathmore', '892.345.3428', '436 Finley Avenue'], ['Frank', 'Burger', '925.541.7625', '662 South Dogwood Way'], ['Heather', 'Albrecht', '548.326.4584', '919 Park Place']]
الگوی :? دونقطهی پس از نام خانوادگی را تطبیق میدهد، بهطوری که این دونقطه در فهرست نتیجه ظاهر نمیشود. با maxsplit برابر 4، میتوانیم شمارهی خانه را از نام خیابان جدا کنیم:
>>> [re.split(":? ", entry, maxsplit=4) for entry in entries] [['Ross', 'McFluff', '834.345.1254', '155', 'Elm Street'], ['Ronald', 'Heathmore', '892.345.3428', '436', 'Finley Avenue'], ['Frank', 'Burger', '925.541.7625', '662', 'South Dogwood Way'], ['Heather', 'Albrecht', '548.326.4584', '919', 'Park Place']]
sub() هر رخداد از یک الگو را با یک رشته یا نتیجهی یک تابع جایگزین میکند. این مثال استفاده از sub() را با یک تابع برای دگرگونسازی (munge) متن، یا تصادفی کردن ترتیب همهی نویسههای هر واژه از یک جمله بهجز نخستین و آخرین نویسه نشان میدهد:
>>> def repl(m): ... inner_word = list(m.group(2)) ... random.shuffle(inner_word) ... return m.group(1) + "".join(inner_word) + m.group(3) ... >>> text = "Professor Abdolmalek, please report your absences promptly." >>> re.sub(r"(\w)(\w+)(\w)", repl, text) 'Poefsrosr Aealmlobdk, pslaee reorpt your abnseces plmrptoy.' >>> re.sub(r"(\w)(\w+)(\w)", repl, text) 'Pofsroser Aodlambelk, plasee reoprt yuor asnebces potlmrpy.'
findall() همه رخدادهای یک الگو را تطبیق میدهد، نه فقط اولین رخداد را آنگونه که search() انجام میدهد. برای مثال، اگر نویسندهای بخواهد همه قیدها را در متنی پیدا کند، ممکن است از findall() به شکل زیر استفاده کند:
>>> text = "He was carefully disguised but captured quickly by police." >>> re.findall(r"\w+ly\b", text) ['carefully', 'quickly']
اگر کسی بخواهد اطلاعات بیشتری دربارهی همهی تطبیقهای یک الگو فراتر از متن تطبیقیافته داشته باشد، finditer() مفید است، زیرا بهجای رشتهها، اشیای Match را فراهم میکند. در ادامهی مثال پیشین، اگر نویسندهای بخواهد همهی قیدها و موقعیتهای آنها را در متنی بیابد، از finditer() به شیوهی زیر استفاده میکند:
>>> text = "He was carefully disguised but captured quickly by police." >>> for m in re.finditer(r"\w+ly\b", text): ... print('%02d-%02d: %s' % (m.start(), m.end(), m.group(0))) 07-16: carefully 40-47: quickly
نمادگذاری رشتهی خام (r"text") عبارتهای باقاعده را قابلمدیر نگه میدارد. بدون آن، برای خنثی کردن هر بکاسلش ('\') در یک عبارت باقاعده باید پیش از آن یک بکاسلش دیگر قرار داد. برای مثال، دو خط کد زیر از نظر عملکرد یکسان هستند:
>>> re.search(r"\W(.)\1\W", " ff ") <re.Match object; span=(0, 4), match=' ff '> >>> re.search("\\W(.)\\1\\W", " ff ") <re.Match object; span=(0, 4), match=' ff '>
وقتی میخواهید یک بکاسلش لفظی را تطبیق دهید، باید آن را در عبارت باقاعده خنثی کنید. با نمادگذاری رشته خام، این به معنای r"\\" است. بدون نمادگذاری رشته خام، باید از "\\\\" استفاده کنید، که سطرهای کد زیر را از نظر عملکردی یکسان میکند:
>>> re.search(r"\\", r"\\") <re.Match object; span=(0, 1), match='\\'> >>> re.search("\\\\", r"\\") <re.Match object; span=(0, 1), match='\\'>
یک توکنساز (tokenizer) یا اسکنر (scanner) رشتهای را تحلیل میکند تا گروههایی از نویسهها را دستهبندی کند. این نخستین گام مفید در نوشتن یک کامپایلر یا مفسر است.
دستههای متن با عبارات باقاعده مشخص میشوند. روش کار این است که آنها را در یک عبارت باقاعدهی اصلی واحد ترکیب کنید و روی تطابقهای متوالی حلقه بزنید:
from typing import NamedTuple import re class Token(NamedTuple): type: str value: int | float | str line: int column: int def tokenize(code): keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'} token_specification = [ ('NUMBER', r'\d+(\.\d*)?'), # Integer or decimal number ('ASSIGN', r':='), # Assignment operator ('END', r';'), # Statement terminator ('ID', r'[A-Za-z]+'), # Identifiers ('OP', r'[+\-*/]'), # Arithmetic operators ('NEWLINE', r'\n'), # Line endings ('SKIP', r'[ \t]+'), # Skip over spaces and tabs ('MISMATCH', r'.'), # Any other character ] tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification) line_num = 1 line_start = 0 for mo in re.finditer(tok_regex, code): kind = mo.lastgroup value = mo.group() column = mo.start() - line_start if kind == 'NUMBER': value = float(value) if '.' in value else int(value) elif kind == 'ID' and value in keywords: kind = value elif kind == 'NEWLINE': line_start = mo.end() line_num += 1 continue elif kind == 'SKIP': continue elif kind == 'MISMATCH': raise RuntimeError(f'{value!r} unexpected on line {line_num}') yield Token(kind, value, line_num, column) statements = ''' IF quantity THEN total := total + price * quantity; tax := price * 0.05; ENDIF; ''' for token in tokenize(statements): print(token)
توکنساز (tokenizer) خروجی زیر را تولید میکند:
Token(type='IF', value='IF', line=2, column=4) Token(type='ID', value='quantity', line=2, column=7) Token(type='THEN', value='THEN', line=2, column=16) Token(type='ID', value='total', line=3, column=8) Token(type='ASSIGN', value=':=', line=3, column=14) Token(type='ID', value='total', line=3, column=17) Token(type='OP', value='+', line=3, column=23) Token(type='ID', value='price', line=3, column=25) Token(type='OP', value='*', line=3, column=31) Token(type='ID', value='quantity', line=3, column=33) Token(type='END', value=';', line=3, column=41) Token(type='ID', value='tax', line=4, column=8) Token(type='ASSIGN', value=':=', line=4, column=12) Token(type='ID', value='price', line=4, column=15) Token(type='OP', value='*', line=4, column=21) Token(type='NUMBER', value=0.05, line=4, column=23) Token(type='END', value=';', line=4, column=27) Token(type='ENDIF', value='ENDIF', line=5, column=4) Token(type='END', value=';', line=5, column=9)
Friedl, Jeffrey. Mastering Regular Expressions. ویرایش سوم، O'Reilly Media، ۲۰۰۹. ویرایش سوم این کتاب دیگر بههیچوجه پایتون را پوشش نمیدهد، اما ویرایش نخست، نوشتن الگوهای خوب عبارت باقاعده را با جزئیات بسیار پوشش میداد.