عبارات منظم چیست؟

عبارات منظم، که به عنوان regex نیز شناخته می‌شوند، با تعریف الگوهایی کار می‌کنند که می‌توانید برای جستجوی کاراکترها یا کلمات خاص در رشته‌ها استفاده کنید.

هنگامی که الگویی را که می خواهید استفاده کنید تعریف کردید، می توانید ویرایش کنید، کاراکترها یا کلمات خاصی را حذف کنید، چیزی را جایگزین چیز دیگری کنید، اطلاعات مربوطه را از یک فایل یا هر رشته ای که حاوی آن الگوی خاص است استخراج کنید و غیره.

چرا باید Regex را یاد بگیرید؟

Regex به شما اجازه می دهد تا پردازش متن را به گونه ای انجام دهید که می تواند در زمان شما صرفه جویی کند. همچنین می تواند سرگرمی را در این فرآیند به شما معرفی کند.

استفاده از regex می تواند مکان یابی اطلاعات را بسیار آسان تر کند. هنگامی که هدف خود را پیدا کردید، می توانید به صورت دسته ای ویرایش/تغییر/حذف یا هر پردازشی که نیاز دارید انجام دهید.

برخی از نمونه‌های عملی استفاده از regex عبارتند از تغییر نام دسته‌ای فایل، تجزیه گزارش‌ها، اعتبارسنجی فرم‌ها، انجام ویرایش‌های انبوه در پایگاه کد و جستجوی بازگشتی.

در این آموزش قصد داریم با کمک این سایت به اصول regex بپردازیم. بعداً، چند چالش regex را معرفی خواهم کرد که با استفاده از پایتون آنها را حل خواهید کرد. من همچنین به شما نشان خواهم داد که چگونه از ابزارهایی مانند sed و grep با regex

مانند بسیاری از چیزهای زندگی، عبارات منظم یکی از آن چیزهایی است که شما فقط با انجام آن می توانید واقعاً درک کنید. من شما را تشویق می‌کنم در حالی که در حال بررسی این مقاله هستید، با regex بازی کنید.

فهرست مطالب

  • اصول Regex
    • مطابقت کامل
    • مجموعه کاراکتر
      • مطابقت محدوده در regex
      • با هر شخصیتی که در مجموعه نیست مطابقت دهید
    • کلاس های شخصیت
    • کمیت کننده ها
    • گرفتن گروه ها
      • نحوه استفاده از OR منطقی در regex
      • نحوه ارجاع به گروه های ضبط
      • نحوه نام گذاری گروه های ضبط
  • نحوه استفاده از regex با ابزارهای خط فرمان
    • جستجوی regex بازگشتی با grep
    • تعویض با sed
  • Advanced Regex: Lookarounds
    • نگاه به پشت
    • پیش بینی ها
  • نمونه های عملی Regex
    • تجزیه سیاهههای مربوط
    • تغییر نام فایل انبوه
    • اعتبار سنجی ایمیل
    • محدودیت های رمز عبور
  • سخنان پایانی


اصول Regex

یک عبارت منظم چیزی نیست جز دنباله ای از کاراکترها که با یک الگو مطابقت دارند. علاوه بر استفاده از کاراکترهای تحت اللفظی (مانند ‘abc’)، برخی از کاراکترهای متا (*،+،؟ و غیره) وجود دارند که اهداف خاصی دارند. همچنین ویژگی هایی مانند کلاس های کاراکتر وجود دارد که می تواند به شما کمک کند عبارات منظم خود را ساده کنید.

قبل از نوشتن هر regex، باید در مورد تمام موارد اساسی و موارد لبه برای الگوی مورد نظر خود بیاموزید.

به عنوان مثال، اگر می‌خواهید با «Hello World» مطابقت داشته باشید، آیا می‌خواهید خط با «سلام» شروع شود یا می‌تواند با هر چیزی شروع شود؟ آیا دقیقاً یک فاصله بین “Hello” و “World” می خواهید یا می تواند بیشتر باشد؟ آیا شخصیت‌های دیگر می‌توانند بعد از «جهان» بیایند یا خط باید به همین جا ختم شود؟ آیا به حساسیت حروف کوچک اهمیت می دهید؟ و غیره.

اینها سوالاتی هستند که قبل از اینکه بنشینید و رژکس خود را بنویسید باید پاسخ آنها را داشته باشید.

مطابقت کامل

ابتدایی ترین شکل regex شامل تطبیق دنباله ای از کاراکترها به روشی مشابه است که می توانید با Ctrl-F در یک ویرایشگر متن انجام دهید.

مطابقت کامل

در بالا می‌توانید تعداد مطابقت‌ها را ببینید، و در پایین توضیحی درباره اینکه regex چه کاراکتری را با کاراکتر مطابقت می‌دهد، ارائه شده است.

مجموعه کاراکتر

مجموعه کاراکترهای Regex به شما این امکان را می دهد که هر یک از شخصیت ها را از یک گروه کاراکتر مطابقت دهید. این گروه با براکت های مربع احاطه شده است [].

مثلا، t[ah]i “تای” و “تی” را منطبق می کند. در اینجا ‘t’ و ‘i’ ثابت هستند اما بین آنها می تواند ‘a’ یا ‘h’ رخ دهد.

match_set

مطابقت محدوده در regex

گاهی اوقات ممکن است بخواهید گروهی از کاراکترها را که ماهیت ترتیبی دارند، مانند هر حرف انگلیسی بزرگ، مطابقت دهید. اما نوشتن هر 26 حرف بسیار خسته کننده خواهد بود.

Regex این مشکل را با محدوده ها حل می کند. “-” به عنوان یک عملگر محدوده عمل می کند. برخی از محدوده های معتبر در زیر نشان داده شده است:

دامنه مسابقات
[A-Z] حروف بزرگ
[a-z] حروف کوچک
[0-9] هر رقمی

همچنین می توانید محدوده های جزئی را مشخص کنید، مانند [b-e] برای مطابقت با هر یک از حروف “bcde” یا [3-6] برای مطابقت با هر یک از اعداد ‘3456’.

match_set_ranges

شما محدود به تعیین تنها یک محدوده در یک مجموعه کاراکتر نیستید. می توانید از چندین محدوده استفاده کنید و همچنین آنها را با هر کاراکتر اضافی دیگری ترکیب کنید. اینجا، [3-6u-w;] با هر یک از ‘3456uvw’ یا نقطه ویرگول ‘;’ مطابقت دارد.

match_set_ranges_multi

با هر شخصیتی که در مجموعه نیست مطابقت دهید

اگر مجموعه را با یک پیشوند «^» قرار دهید، عملیات معکوس انجام خواهد شد. مثلا، [^A-Z0-9] با هر چیزی به جز حروف بزرگ و اعداد مطابقت دارد.

match_set_not

کلاس های شخصیت

در حین نوشتن regex، باید گروه‌های خاصی مانند ارقام را اغلب و چندین بار در یک عبارت مطابقت دهید.

برای مثال، چگونه می‌توانید با الگویی مانند “حرف-رقم-حرف-رقم” مطابقت دهید؟

با آنچه تاکنون آموخته اید، می توانید به آن دست پیدا کنید [a-zA-Z]-[0-9]-[a-zA-z]-[0-9]. این کار می کند، اما می توانید ببینید که چگونه با بزرگتر شدن طول الگو، بیان می تواند کاملاً آشفته شود.

برای ساده‌تر کردن عبارت، کلاس‌ها به گروه‌های کاراکتری کاملاً تعریف‌شده مانند اعداد اختصاص داده شده‌اند. جدول زیر این کلاس ها و عبارت معادل آنها را با مجموعه کاراکترها نشان می دهد:

کلاس مسابقات عبارت معادل
. هر چیزی به جز خط جدید [^\n\r]
\w شخصیت کلمه [a-zA-Z0-9_]
\ W شخصیت غیر کلمه ای [^\w]
\d ارقام [0-9]
\ D غیر رقمی [^\d]
\s فضا، برگه، خطوط جدید [ \t\r\n\f]
\S کاراکترهای بدون فضای خالی [^\s]

کلاس های کاراکتر بسیار مفید هستند و عبارات شما را بسیار تمیزتر می کنند. ما از آنها به طور گسترده در طول این آموزش استفاده خواهیم کرد، بنابراین می توانید از این جدول به عنوان یک نقطه مرجع استفاده کنید و اگر هر یک از کلاس ها را فراموش کردید به اینجا بازگردید.

بیشتر اوقات، ما به همه موقعیت ها در یک الگو اهمیت نمی دهیم. “.” class ما را از نوشتن تمام کاراکترهای ممکن در یک مجموعه نجات می دهد.

مثلا، t.. با هر چیزی که با t و هر دو کاراکتر بعد از آن شروع می شود مطابقت دارد. این ممکن است شما را به یاد SQL بیاندازد LIKE اپراتور که استفاده می کند t%% برای انجام همان کار

مطابقت_هر کدام

کمیت کننده ها

کلمه «الگو» و «تکرار» دست به دست هم می دهند. اگر می خواهید یک عدد 3 رقمی را مطابقت دهید می توانید از آن استفاده کنید \d\d\d. اما اگر بخواهید 11 رقم را مطابقت دهید چه؟ شما می توانید 11 بار ‘\d’ بنویسید، اما یک قانون کلی در حین نوشتن regex یا هر نوع برنامه نویسی این است که اگر متوجه شدید چیزی را بیش از دو بار تکرار می کنید، احتمالاً از برخی ویژگی ها بی اطلاع هستید.

در regex می توانید از کمیت کننده ها برای این منظور استفاده کنید. برای مطابقت با 11 رقم، می توانید به سادگی عبارت را بنویسید \d{11}.

جدول زیر کمیت کننده هایی را که می توانید در regex استفاده کنید فهرست می کند:

کمیت کننده مسابقات
* 0 یا بیشتر
? 0 یا 1
+ 1 یا بیشتر
{n} دقیقا n بار
{n،} n بار یا بیشتر
{n، m} n تا m بار شامل

در این مثال، عبارت can\s+write مسابقات can به دنبال آن 1 یا چند فاصله سفید و به دنبال آن write. اما می‌توانید ببینید که «canwrite» مطابقت ندارد \s+ یعنی حداقل یک فضای خالی باید مطابقت داده شود. این زمانی مفید است که در حال جستجوی متنی هستید که بریده نشده است.

match_multi_whitespaces

می توانید حدس بزنید چه چیزی can\s?write مطابقت خواهد داشت؟

گرفتن گروه ها

گروه‌های ضبط عبارت‌های فرعی هستند که در داخل پرانتز قرار گرفته‌اند (). شما می توانید هر تعداد گروه عکسبرداری و حتی گروه های ضبط تودرتو داشته باشید.

بیان (The ){2} دو بار با ‘The’ مطابقت دارد. اما بدون گروه گرفتن، بیان The {2} با “The” و به دنبال آن 2 فاصله مطابقت دارد، زیرا کمیت بر روی کاراکتر فاصله اعمال می شود و نه در “The” به عنوان یک گروه.

capture_this

شما می توانید هر الگوی را در داخل گروه های ضبط مطابق با هر regex معتبری مطابقت دهید. اینجا (is\s+){2} منطبق است اگر پیدا کند “است” دو بار 1 یا بیشتر فاصله دارد.

capture_is

نحوه استفاده از OR منطقی در regex

می توانید از “|” استفاده کنید برای مطابقت با الگوهای متعدد This is (good|bad|sweet) “این” با هر یک از “خوب” یا “بد” یا “شیرین” منطبق می شود.

یا

باز هم، شما باید اهمیت گروه های ضبط را در اینجا درک کنید. در مورد چه بیانی فکر کنید This is good|bad|sweet مطابقت دارد؟

پیشنهاد می‌کنیم بخوانید:  چه کسی بیت کوین را کنترل می کند؟

or_no_capture

با یک گروه اسیر، good|bad|sweet جدا شده است This is . اما اگر در داخل یک گروه ضبط نباشد، کل regex فقط یک گروه است. پس بیان This is good|bad|sweet اگر رشته حاوی “این خوب است” یا “بد” یا “شیرین” باشد مطابقت خواهد داشت.

نحوه ارجاع به گروه های ضبط

گروه‌های کپچر را می‌توان در همان عبارت یا در حین انجام جایگزینی که در برگه جایگزینی مشاهده می‌کنید ارجاع داد.

بیشتر ابزارها و زبان‌ها به شما امکان می‌دهند به nامین گروه ضبط‌شده با ‘\n’ ارجاع دهید. در این سایت از $n هنگام ارجاع به جایگزینی استفاده می شود. نحو برای جایگزینی بسته به ابزار یا زبانی که استفاده می کنید متفاوت خواهد بود. برای مثال، برای جاوا اسکریپت، ‘$n’، در حالی که برای پایتون ‘\n’ است.

در بیان (This) is \1 power، “این” گرفته می شود و سپس با “\1” ارجاع داده می شود که به طور موثر مطابقت دارد This is This power.

refer_capture

نحوه نام گذاری گروه های ضبط

شما می توانید گروه های ضبط خود را با نحو نام گذاری کنید (?<name>pattern) و آنها را در همان عبارت با ارجاع مجدد دهید \k<name>.

در تعویض، ارجاع توسط انجام می شود $<name>. این نحو برای جاوا اسکریپت است و می تواند در بین زبان ها متفاوت باشد. در اینجا می توانید با تفاوت ها آشنا شوید. همچنین توجه داشته باشید که این ویژگی ممکن است در برخی از زبان ها موجود نباشد.

در بیان (?<lang>[\w+]+) is the best but \k<lang> .*، الگو [\w+]+ با نام “lang” گرفته می شود و با ارجاع مجدد می یابد \k<lang>. این الگو 1 بار یا بیشتر با هر کاراکتر کلمه یا نویسه «+» مطابقت دارد. این .* در پایان regex با هر کاراکتری 0 یا بیشتر برابر است. و در نهایت در تعویض، ارجاع توسط انجام می شود $<lang>.

با نام_گرفتن

نحوه استفاده از Regex با ابزارهای خط فرمان

ابزارهای CLI خوبی در دسترس هستند که به شما امکان می دهند از ترمینال خود regex انجام دهید. این ابزارها حتی در زمان شما صرفه جویی می کنند زیرا می توانید به راحتی regex های مختلف را بدون نوشتن کد در برخی از زبان ها و سپس کامپایل یا تفسیر آن آزمایش کنید.

برخی از ابزارهای شناخته شده grep، sed و awk هستند. بیایید به چند مثال نگاه کنیم تا به شما ایده هایی در مورد چگونگی استفاده از این ابزارها ارائه دهیم.

جستجوی regex بازگشتی با grep

می توانید قدرت regex را از طریق grep اجرا کنید. Grep می تواند الگوها را در یک فایل جستجو کند یا جستجوی بازگشتی انجام دهد.

اگر در ویندوز هستید، می توانید grep را با استفاده از winget نصب کنید. این دستور را در powershell اجرا کنید:

winget install -e --id GnuWin32.Grep

من راه حل چالشی را که برای یک مسابقه CTF در دانشگاهم ایجاد کردم به شما نشان خواهم داد.

فایل ضمیمه شده به چالش یک فایل فشرده است که شامل چندین سطح دایرکتوری و فایل های زیادی در آن است. نام مسابقه Coderush با فرمت پرچم بود coderush{flag is here}. بنابراین باید الگو را جستجو کنید coderush{.*} که با فرمت پرچم مطابقت دارد coderush{any character here}.

فایل را از حالت فشرده خارج کنید unzip ripG.zip و سی دی به آن با cd ripG.

فایل های عظیم

358 دایرکتوری و 8731 فایل وجود دارد. به جای جستجوی تک تک الگوها در فایل ها، می توانید grep را به صورت زیر به کار ببرید:

grep --color -R "coderush{.*}"

پرچم “-R” جستجوی بازگشتی را فعال می کند.

جستجوی بازگشتی با grep

در اینجا می‌توانید درباره grep و گزینه‌های خط فرمان آن اطلاعات بیشتری کسب کنید

تعویض با sed

شما می توانید از sed برای درج، حذف، جایگزینی روی فایل های متنی با تعیین regex استفاده کنید. اگر در ویندوز هستید، می توانید sed را از اینجا دریافت کنید. یا اگر از WSL استفاده می کنید، ابزارهایی مانند grep و sed از قبل در دسترس خواهند بود.

این رایج ترین استفاده از sed است:

sed 's/pattern/replacement/g' filename
echo "${text}" | sed 's/pattern/replacement/g'

در اینجا گزینه “g” برای جایگزینی همه رخدادها مشخص شده است.

برخی دیگر از گزینه های مفید هستند -n برای سرکوب رفتار پیش‌فرض چاپ تمام خطوط و استفاده از p به جای g برای چاپ تنها خطوطی که تحت تأثیر regex قرار دارند.

بیایید نگاهی به محتوای texts.txt بیندازیم.

Hello rand chars World 56 rand chars
Henlo 52 rand chars W0rld rand chars
GREP rand chars Henlo 62 rand chars
Henlo 10 rand chars Henlo rand chars
GREP rand chars Henlo 45 rand chars

وظیفه ما جایگزینی است Henlo number با Hello number فقط در خطوطی که “GREP” وجود دارد. بنابراین، ما به دنبال الگو هستیم Henlo ([0-9]+) که با «هنلو» مطابقت دارد و با 1 یا چند رقم همراه می شود و همه ارقام گرفته می شوند. سپس رشته جایگزین ما خواهد بود Hello \1 – ‘\1’ به گروه ضبط حاوی ارقام ارجاع می دهد.

یکی از راه‌های انجام این کار، استفاده از grep برای grep خطوطی است که دارای “GREP” هستند و سپس جایگزینی را با sed انجام دهید.

grep "GREP" texts.txt | sed -En 's/Henlo ([0-9]+)/Hello \1/p'

گزینه “-E” regex گسترده ای را فعال می کند که بدون آن باید از پرانتز فرار کنید.

grep_sed

یا فقط می توانید از sed استفاده کنید. استفاده کنید /pattern/ برای محدود کردن جایگزینی فقط در خطوطی که الگو وجود دارد.

sed -En '/GREP/ s/Henlo ([0-9]+)/Hello \1/p' texts.txt

Advanced Regex: Lookarounds

Lookaheads و Lookbehinds (با هم به عنوان lookarounds شناخته می‌شوند) ویژگی‌های regex هستند که به شما امکان می‌دهند وجود یک الگو را بدون درج آن در مسابقه بررسی کنید.

شما می توانید آنها را به عنوان ادعاهای عرض صفر در نظر بگیرید – آنها وجود یک الگو را تایید می کنند اما هیچ کاراکتری را در مسابقه مصرف نمی کنند. اینها ویژگی های بسیار قدرتمندی هستند، اما از نظر محاسباتی نیز گران هستند. بنابراین اگر اغلب از آنها استفاده می کنید، مطمئن شوید که عملکرد را زیر نظر داشته باشید.

نگاه به پشت

فرض کنید می خواهید کلمه “لینوکس” را مطابقت دهید، اما 2 شرط دارید.

  1. کلمه “GNU” باید قبل از “linux” وجود داشته باشد. اگر خطی حاوی ‘linux’ باشد اما قبل از آن ‘GNU’ نداشته باشد، می خواهیم آن خط را کنار بگذاریم.
  2. ما فقط می خواهیم مطابقت داشته باشیم linux و دیگر هیچ.

ما قبلاً می دانیم که چگونه شرط اول را برآورده کنیم. GNU.* “GNU” و با هر تعداد کاراکتر مطابقت دارد. سپس در نهایت کلمه را مطابقت می دهیم linux. این با همه مطابقت دارد GNU-any-characters-linux.

GNU_LINUX

اما چگونه از تطابق جلوگیری کنیم GNU.* در حالی که هنوز شرایط 1 را حفظ می کنید؟

اینجاست که یک نگاه مثبت وارد می‌شود. می‌توانید با قرار دادن پیشوند یک گروه عکس‌برداری به عنوان یک نگاه مثبت به آن علامت بزنید. ?<=. در این مثال، عبارت تبدیل می شود (?<=GNU.*)linux.

مثبت_نگاه به پشت

فقط الان linux مطابقت دارد و هیچ چیز دیگری

توجه داشته باشید که عبارات (?<=GNU.*)linux و linux(?<=GNU.*) دقیقاً همین رفتار را خواهد داشت. اگر چه در عبارت دوم linux قبل از نگاه پشت، وجود دارد .* بعد از “GNU” که مطابقت دارد linux. این بدان معنی است که نگاه پشت سر را راضی می کند.

برای ساده‌تر کردن آن، به الگوی بدون ظاهر فکر کنید. الگو GNU.* در مورد ما تطبیق با ‘GNU’ و هر چیزی پس از آن مطابقت دارد linux.

اکنون می‌توانیم یک عبارت تعمیم‌یافته استخراج کنیم که عبارت (?<=C)X با الگوی X مطابقت دارد – فقط اگر الگوی C قبل از X آمده باشد (و C نباید در تطابق گنجانده شود).

همچنین می توانید شرط 1 را معکوس کنید. خطوطی را که حاوی کلمه هستند مطابقت دهید linux فقط اگر GNU هرگز قبل از آن نیامده است به این می گویند نگاه منفی به پشت سر. پیشوند در این مورد است ?<!. برعکس عبارت قبلی خواهد بود (?<!GNU.*)linux.

منفی_نگاه به پشت

پیش بینی ها

همانطور که در مثال قبلی دیدید، پیش‌بینی‌ها نیز ادعاهایی مانند نگاه به عقب هستند. تنها تفاوت این است که lookbehinds قبل از آن ادعا می کند و lookaheads بعد از آن ادعا می کند.

فرض کنید این دو شرط را دارید:

  1. همخوانی داشتن Hello فقط اگر World جایی بعد از آن می آید
  2. فقط با سلام و هیچ چیز دیگری مطابقت دارد.

پیشوند یک نگاه مثبت است ?=. بیان Hello(?=.*World) هر دو شرط را برآورده خواهد کرد. این شبیه به Hello.*World به جز این فقط Hello مطابقت خواهد داشت در حالی که Hello.*World “Hello”، “World” و هر چیزی در این بین مطابقت دارد.

postitive_lookahead

شبیه به مثال در نگاه مثبت به پشت، عبارات Hello(?=.*World) و (?=.*World)Hello معادل هستند. از آنجا که .* قبل از مسابقات جهانی Hello، ارضای شرط 1.

یک نگاه منفی فقط مکمل یک نگاه منفی به پشت سر است. شما می توانید آن را با پیشوند آن استفاده کنید ?!. (?!World)Hello مطابقت خواهد داشت Hello فقط در صورتی که وجود نداشته باشد World هر جایی بعد از آن

negative_lookahead

در اینجا خلاصه‌ای از نحو برای بررسی‌های زمانی است که می‌خواهید الگوی X را با ادعای C مطابقت دهید.

عمل RegEx
نگاه مثبت به آینده (?=C)X
نگاه منفی (?!C)X
نگاه مثبت به پشت (?<=C)X
نگاه منفی به پشت (?<!C)X

نمونه های عملی Regex

تجزیه سیاهههای مربوط

در این فایل لاگ، این خطوطی هستند که به آنها اهمیت می دهیم:

[1/10000] Train loss: 11.30368, Valid loss: 8.95446, Elapsed_time: 7.58941
[500/10000] Train loss: 0.96180, Valid loss: 0.20098, Elapsed_time: 82.48651
[1000/10000] Train loss: 0.04051, Valid loss: 0.11927, Elapsed_time: 156.86243

وظیفه ما استخراج از دست دادن آموزش و از دست دادن اعتبار برای اهدافی مانند ترسیم ضرر در طول دوره هاست. ما باید مقادیر از دست دادن تمرین را استخراج کنیم 11.30368, 0.96180, 0.04051 و آنها را در یک آرایه قرار دهید.

پیشنهاد می‌کنیم بخوانید:  چه کسی اتریوم را به عنوان پرداخت می پذیرد؟ 8 مکان که می توانید ETH خرج کنید

همه مقادیر مربوطه با پیشوند ‘ هستندTrain loss: ‘، بنابراین ما می توانیم از آن در regex خود همانطور که هست استفاده کنیم. برای تطبیق اعداد شناور، باید تعدادی از ارقام را با یک ” مطابقت دهیم..” و سپس ارقام بیشتری به دنبال آن می آیند. می توانید این کار را با \d+\.\d+. از آنجا که ما می خواهیم این اعداد را پیگیری کنیم، آنها باید در یک گروه ضبط باشند.

مانند “.” هنگامی که می خواهید یک “” را مطابقت دهید، در regex هدف خاصی دارد. شخصیت شما باید با یک بک اسلش از آن فرار کنید. این برای همه کاراکترهای با هدف خاص قابل اجرا است. اما لازم نیست از آن در داخل مجموعه شخصیت ها فرار کنید.

در مجموع، عبارت استخراج ضرر تمرینی است Train loss: (\d+\.\d+). می‌توانیم از همین منطق برای استخراج از دست دادن اعتبار استفاده کنیم Valid loss: (\d+\.\d+).

در اینجا یک راه برای استخراج این اطلاعات با استفاده از پایتون وجود دارد:

import re

f = open("log_train.txt", "r").read()

train_loss = re.findall(r'Train loss: (\d+\.\d+)', f)
valid_loss = re.findall(r'Valid loss: (\d+\.\d+)', f)

train_loss = [float(i) for i in train_loss]
valid_loss = [float(i) for i in valid_loss]

print("train_loss =", train_loss)
print("")
print("valid_loss =", valid_loss)

وقتی یک گروه اسیر وجود دارد، re.findall تمام خطوط را جستجو می کند و مقادیر داخل گروه ضبط را در یک لیست برمی گرداند.

هر تابع regex فقط رشته ها را برمی گرداند، بنابراین مقادیر به شناور تبدیل شده و چاپ می شوند. سپس می توانید مستقیماً از آنها در اسکریپت پایتون دیگری به عنوان لیستی از شناورها استفاده کنید.

این هم نتیجه:

استخراج_از دست دادن

همچنین می توانید از sed استفاده کنید، خروجی را در train_losses.txt ذخیره کنید و از روی فایل بخوانید. ابتدا از ‘/Train/’ استفاده می کنیم تا فقط خطوطی را که ‘Train’ موجود است هدف قرار دهیم سپس همان regex قبلی را اعمال می کنیم.

sed -En '/Train/ s/.*Train loss: ([0-9]+\.[0-9]+).*/\1/p' log_train.txt | tee train_losses.txt

“.*” در ابتدا و انتها اضافه می شود تا sed با محتوای تمام خطوط مربوطه مطابقت داشته باشد. سپس کل خط با مقدار گروه ضبط جایگزین می شود. این tee از دستور برای تغییر مسیر خروجی sed به train_losses.txt استفاده می شود و در عین حال محتویات را در ترمینال چاپ می کند.

extract_loss_sed

لحظه ای به این فکر کنید که برای استخراج دوره ها به چه چیزی نیاز دارید. شما باید 500 را از آن استخراج کنید [500/10000] برای همه این خطوط آرایه باید شبیه باشد [1, 500, 1000, 1500, …]. می توانید همان روشی را که برای مثال قبلی استفاده کردیم دنبال کنید.

توجه داشته باشید که اگر می خواهید مطابقت داشته باشید “[” or “]“، شما باید از آن فرار کنید. پاسخ در اینجا داده شده است.

تغییر نام فایل انبوه

شما این فایل ها را با مقادیری تصادفی به عنوان پیشوند دارید. شما باید همه فایل ها را به 1.mp4، 2.mp4 و غیره تغییر نام دهید.
به این ترتیب فایل ها تولید شدند.

create_files

این یک سناریوی معمولی است که در آن شما لیستی از فایل‌ها را دارید که شماره ترتیب آنها در نام وجود دارد، اما تعدادی کاراکتر دیگر نیز وجود دارد که شما نمی‌خواهید.

این الگو باید با هر قسمتی مطابقت داشته باشد، سپس یک خط زیر و سپس عدد و .mp4 در پایان.

مقدار مربوطه عدد قبل از ‘.mp4’ است که در یک گروه ضبط قرار می دهیم. .*Episode_ همه چیز را با تعداد مطابقت خواهد داد. سپس ما می توانیم عدد را با ([0-9]+) و همچنین .mp4 را با \.mp4.

بنابراین regex نهایی است .*Episode_([0-9]+)\.mp4. همانطور که می خواهیم حفظ کنیم .mp4 رشته جایگزین خواهد بود \1.mp4.

این یکی از راه های حل آن با استفاده از sed است.

for i in *.mp4; do
    newname=$(echo $i | sed -En 's/.*Episode_([0-9]+)\.mp4/\1.mp4/p')
    mv $i $newname
done;ls

ابتدا نام جدید در یک متغیر ذخیره می شود و سپس از دستور mv برای تغییر نام فایل استفاده می شود.

انبوه_تغییر نام

می توانستیم فقط استفاده کنیم .* در محل .*Episode_ ? در این مثال، بله. اما ممکن است نام فایل هایی مانند Steins_Gate0.mp4 جایی که 0 بخشی از نام فیلم است و شما واقعاً نمی خواستید نام این فایل را تغییر دهید، بنابراین همیشه بهتر است تا حد امکان خاص باشد.

اگر برخی از فایل ها به عنوان “Random_Episode6.mp4” نامگذاری شوند چه می شود؟ تفاوت این است که بعد از قسمت هیچ خط خطی وجود ندارد. چه تغییری باید ایجاد کنید؟

پاسخ این است که شما باید یک “?” اضافه کنید. بعد از “_” آن را اختیاری کنید. regex خواهد بود .*Episode_?([0-9]+)\.mp4.

اعتبار سنجی ایمیل

انواع و اقسام regex پیچیده برای اعتبارسنجی ایمیل وجود دارد.

در اینجا یک مورد ساده است: ^[^@ ]+@[^@.]+\.\w+$. با فرمت مطابقت دارد A@B.C

جدول زیر این الگو را به قطعات کوچکتر تقسیم می کند:

الگو مسابقات
^ شروع خط
[^@ ]+ هر چیزی به جز “@” و کاراکتر فاصله
@[^@.]+ @ به دنبال هر چیزی به جز “@” و “.” شخصیت ها
\.\w+ “.” به دنبال کاراکترهای کلمه
$ آخر خط

email_validation

در سایت regexr می توانید پرچم چند خط را از تب Flags در گوشه سمت راست بالا فعال کنید. “gm” در پایان نشان می دهد که پرچم چند خطی فعال است.

می بینیم که خط 2،3،5،6 مطابقت نداشت. آیا می توانید دلیل و اینکه کدام قسمت از regex مسئول رد صلاحیت آن است؟

پاسخ در اینجا داده شده است

محدودیت های رمز عبور

همچنین می توانید از regex برای اعمال محدودیت استفاده کنید. در اینجا ما قدرت پیش بینی های مثبت را کشف خواهیم کرد.

فرض کنید می خواهیم یک رشته را فقط در صورتی بپذیریم که یک رقم در آن وجود داشته باشد. شما قبلاً می دانید که چگونه یک رقم را با کلاس ‘\d’ پیدا کنید. برای انجام آن، می توانیم استفاده کنیم [^\d]*\d. این کار با هر کاراکتر غیر رقمی 0 یا بیشتر برابر می شود و سپس با یک رقم مطابقت می کند.

ما همچنین می توانیم از عبارت استفاده کنیم .*\d برای مطابقت با یک رقم بنابراین اگر هیچ رقمی در رشته وجود نداشته باشد، پیش بینی از کار خواهد افتاد و هیچ یک از کاراکترهای آن رشته مطابقت داده نمی شود و یک رشته خالی “” را برمی گرداند.

هنگامی که از یک زبان برنامه نویسی استفاده می کنیم، می توانیم بررسی کنیم که آیا regex یک رشته خالی برگردانده است و تعیین کنیم که محدودیت ها برآورده نشده اند.

ما یک regex ایجاد خواهیم کرد که معیارهای زیر را اعمال می کند:

  1. حداقل 8 کاراکتر و حداکثر 16 کاراکتر.
  2. حداقل یک حرف کوچک.
  3. حداقل یک حرف بزرگ.
  4. حداقل یک عدد

برای رسیدن به این هدف، می‌توانید از چشم‌اندازهای مثبت استفاده کنید. این regex است:

^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,16}$

جدول زیر توضیح می دهد که کدام قسمت از regex چه محدودیتی را اعمال می کند:

الگو محدودیت تحمیلی
.{8,16} حداقل 8 و حداکثر 16 کاراکتر
(?=.*[a-z]) حداقل یک حرف کوچک
(?=.*[A-Z]) حداقل یک حرف بزرگ
(?=.*\d) حداقل یک رقمی

pass_constraints

برای اعمال حداقل 5 حرف بزرگ به چه اصلاحی نیاز دارید؟

ممکن است فکر کنید (?=.*[A-Z]{5,}) کار را انجام خواهد داد. اما این عبارت مستلزم این است که همه 5 حرف با هم باشند. یک رشته مانند rand-ABCDE-rand مطابقت خواهد داشت اما 0AxBCDxE0 با وجود اینکه دارای 5 حرف بزرگ (چون مجاور نیستند) مطابقت نخواهد داشت.

با این حال، ما گروه های اسیر را داریم که به کمک می آیند. می خواهیم 5 حرف بزرگ را در هر نقطه از رشته با هم تطبیق دهیم. ما قبلاً می دانیم که می توانیم 1 حرف بزرگ را با آن مطابقت دهیم .*[A-Z]. اکنون آنها را در یک گروه ضبط قرار می دهیم و یک کمیت حداقل 5 را به آن اضافه می کنیم (.*[A-Z]){5,}.

در اینجا پاسخ نهایی است:

در محل (?=.*[A-Z]) شما نیاز خواهید داشت (?=(.*[A-Z]){5,}). بیان می شود ^(?=.*[a-z])(?=(.*[A-Z]){5,})(?=.*\d).{8,16}$.

pass_5_upper

همچنین می‌توانید برای اعمال گذرواژه‌های قوی‌تر بخواهید که رمز عبور حاوی کلمات خاصی نباشد.

به عنوان مثال، ما می خواهیم رمز عبور را در صورت وجود رد کنیم pass یا 1234. نگاه های منفی ابزاری برای این کار است. regex خواهد بود ^(?!.*(pass|1234)).*$.

limited_words-1

در این regex قرار می دهیم pass و 1234 داخل یک گروه ضبط و از عملگر منطقی OR استفاده کرد. این گروه ضبط در داخل گروه ضبط دیگری که پیشوند با آن است، تودرتو است ?!.*. این باعث می‌شود که آن یک نگاه منفی باشد که در صورت وجود حداقل 8 کاراکتر مطابقت دارد .{8,} با این شرط که، pass یا 1234 نمی تواند در هیچ نقطه ای از رشته وجود داشته باشد.

کلمات پایانی

امیدوارم در حین گذراندن این مقاله، تمرین خوبی داشته باشید. اگر مقداری نحو را فراموش کنید اشکالی ندارد. آنچه مهم است درک مفاهیم اصلی و داشتن ایده خوبی از آنچه با regex امکان پذیر است. سپس، اگر یک الگو را فراموش کردید، می توانید آن را در گوگل جستجو کنید یا به یک چیت شیت مراجعه کنید.

هرچه بیشتر تمرین کنید، بدون کمک خارجی بیشتر به نتیجه خواهید رسید. در نهایت می توانید regex فوق العاده پیچیده و موثر را کاملا آفلاین بنویسید.

در حال حاضر چند برگه چیت regex خوب وجود دارد، بنابراین من می‌خواستم چیزی عمیق‌تر در اینجا ایجاد کنم که بتوانید برای مفاهیم اصلی و موارد استفاده رایج به آن مراجعه کنید.

اگر به دنبال یک چیت شیت هستید، یکی از QuickRef مفید است. این مکان خوبی برای یادآوری نحو است و همچنین مروری کلی از توابع مربوط به regex در زبان های برنامه نویسی مختلف ارائه می دهد.

بیشتر تکنیک‌های regex در همه زبان‌ها و ابزارهای برنامه‌نویسی یکسان هستند – اما برخی ابزارها ممکن است ویژگی‌های اضافی را ارائه دهند. بنابراین در مورد ابزاری که استفاده می کنید تحقیق کنید تا بهترین مورد را برای خود انتخاب کنید.

پیشنهاد نهایی من این است که به زور از regex استفاده نکنید فقط به این دلیل که می توانید. خیلی از مواقع معمولی string.find() برای انجام کار کافی است اما اگر در ترمینال زندگی می کنید، مطمئناً می توانید کارهای زیادی را فقط با regex انجام دهید.