Back End Developer
رگولار اکسپرشن (Regular expression) به زبان ساده
رگولار اکسپرشن چیست؟
مجموعه ای از کاراکترها و علائمی است که می توان با آن قسمتی از یک عبارت، یا نوشته را به اصطلاح Match کرد (قسمتی از عبارت که با پترن مذکور مرتبت می باشد را با آن پیدا کرد).
چه استفاده هایی دارد؟
از رگولار اکسپرشن می توان در validate کردن فیلد های فرم، برای اطمینان از اینکه پسوردی که کاربر وارد می کند شامل یکسری حروف و یا پترنی که ما می خواهیم باشد، برای استخراج تکه ای از یک عبارت، برای پیدا کردن قسمتی از لاگ یک وبسرور که به دنبالش هستیم و ...استفاده کرد.
به چه روشی می توان از آن استفاده کرد؟
تمامی زبان های برنامه نویسی کلاس ، آبجکت و یا توابعی برای کار کردن با رگولار اکسپرشن دارند که می توان با مراجعه به راهنمای آنها از نحوه استفاده از آنها مطلع شد.
نکاتی راجب ادامه این پست
در ادامه از ترجمه اسامی کاراکترهای رگولار اکسپرشن به دلیل اینکه دانستن نام انگلیسی آنها الزامی است خودداری می کنم.
در طول توضیحات از کلمه match زیاد استفاده می شود که معنایش آن است که یک عبارت با یک عبارت دیگر برابر و یکسان باشد.
همچنین منظور از کارکتر یعنی هر حرف انگلیسی یا هر عدد و یا هر علامتی که معمولا روی تمامی کیبورد های استاندارد وجود دارد.
در مثال های زیر پترن regular expression که به اختصار regex هم نوشته می شود را در داخل "..." نوشته ام ولی مثلا در جاوا اسکریپت این پترن در داخل /.../ نوشته می شود.
در ضمن به خاطر محدودیت ادیتور ویرگول در مثال هایی که در ادامه خواهید دید عبارات match شده درون مثال ها در داخل دو * نمایش داده میشوند.
آموزش Regular expression
1. Basic Matchers
به طور کلی کاراکترهای انگلیسی و عددها به خودی خود یک پترن به حساب می آیند.
"regex" => I am learning *regex* in this tutorial.
2. Full stop .
کاراکتر . یا همان نقطه هر تک کاراکتری را به جز new line یا همان n\ را match می کند.
".ar" => The *car* is *par*ked outside.
3. Character set (character class)
کروشه یا کمانک یا همان براکت باز و بسته [ ] که می توان مجموعهای از کارکترها را درون آن قرار داد می تواند یکی از کارکترهای درون آن را در یک متن match کند.
"[pd]ark" => This would match both *park* and *dark*.
و یا می توان با استفاده از dash یا hyphen یا همان - یک range از کاراکتر ها را در داخل [ ] مشخص کرد.
"[a-c]r" => This would match *ar* *br* *cr*
نکته: Full stop یا نقطه درون [.] به معنای نقطه می باشد و نه موردی که در شماره ۲ توضیح داده شد.
4. Repetitions (The start *)
کاراکتر * بعد از هر کاراکتر دیگری که بیاید به معنای هیچ و یا بیشتر تکرار کارکتری که بعد از آن آمده می باشد. به معنای ساده تر مثلا *a یعنی که یا a وجود ندارد و یا می تواند یکبار و یا بیشتر در کلمه یا عبارت وجود داشته باشد.
"ca*r" => *cr* *car* *caaar* *caaaar*
5. Repetitions (The Plus +)
کاراکتر + بعد از هر کاراکتر دیگری که بیاید به معنای یک یا بیشتر تکرار کاراکتری است که بعد از آن آمده می باشد.
"ca+r" => cr *car* *caar*
6. Braces ( quantifiers {} )
این کاراکتر به معنای تعداد تکرار کاراکتر و یا گروه پیش از خودش می باشد مثلا {3,2}[9-0] یعنی حداقل دو عدد و حداکثر سه عدد را match کن، می توان عدد دوم را حذف کرد {,3}[9-0] که به معنای حداقل سه عدد و حداکثر بینهایت و در صورتی که علامت , هم حذف شود {3}[9-0] به معنای دقیقا تکرار سه عدد میباشد.
"[0-9]{2,3}" => Part of this number *992*5 and all of *23* would be mached.
7. Capturing Group (...)
پترنی یا در اصطلاح (sub patternی) که داخلی پرانتز نوشته میشود capturing group نامیده میشود و برای گروه بندی کردن کاراکترها می باشد و اگر بعد از یک capture group موارد ۴، ۵، ۶ را قرار دهیم کل پترن داخل آن طبق توضیحات ۳ قسمت بالا تکرار می شود. مثلا +(ab) یعنی کلی ab حداقل یک و یا بیش از یک بار تکرار می شود.
نکته: در برخی از زبانهای برنامه نویسی مثلا جاوااسکریپت و پایتون توابعی وجود دارد که مقدار داخلی capture group را از متن جدا می کنند و بر می گردانند و علت این نامگذاری (capture) یه همین دلیل میباشد.
8. Non-capturing group (?: )
همانند مورد بالا می باشد ولی با این تفاوت که هیچ مقداری را از داخلی متن match شده باز نمی گرداند.
"c(?:ar)" => *car* *car*bon
9. Alternation |
کاراکتر | یا همان vertical bar به معنای همان or در برنامه نویسی میباشد و از آن می توان در حالت ۱ (basic matchers) و یا در capturing groups یا non-capturing groups استفاده کرد.
"(T|t)he|car" => *The car* is parked in *the* garage.
10. Escaping special character \
برای استفاده کردن از برخی از کاراکترها که به عنوان کاراکتر های پیش فرض رگولار اکسپرشن هستند باید آنها را در اصطلاح escape کرد و بدین معنا که قبل از آنها از escape character یا همان \ استفاده کرد.
کاراکتر های پیش فرض رگولار اکسپرشن که باید آنها را escape کرد: { } [ ] / \ + * . $ ^ | ?
"mat\." => The fat cat sat on the *mat.*
11. Caret ^
قرار دادن کاراکتر ^ در ابتدای یک پترن به معنای این است که عبارت با کاراکتر مذکور باید در ابتدای متن یا عبارتی که می خواهیم match کنیم باشد.
"(T|t)he" => *The* car is parked in *the* garage.
"^(T|t)he" => *The* car is parked in the garage.
نکته: قرار دادن این کاراکتر در ابتدای [ ^] به معنای عکس مقادیری است که درون [ ] قرار دارد.
12. Dollar $
قرار دادن کاراکتر $ در انتهای یک پترن به معنای این است که عبارت با کاراکتر آخری که $ بعد از آن آمده باید در انتهای عبارتی که می خواهیم match کنیم باشد.
"(at\.)" => The fat c*at.* s*at.* on the m*at.*
"(at\.)$" => The fat cat. sat. on the m*at.*
13. The Question Mark
کاراکتر یا همان علامت ? به معنای هیچ و یا فقط یک می باشد.
"[T]he" => *The* car is parked in *the* garage.
"[T]?he" => *The* car is parked in t*he* garage.
14. Shorthand Character Sets
رگولار اکسپرشن یک سری کاراکترهای مختصر برای match کردن یک سری از پترن های پرکاربر دارد.
- کاراکتر . یا همان full stop که هر کاراکتری به جز n\ را match میکند
- کاراکتر w\ که کاراکتر های به اصطلاح alphanumeric را match میکند [a-zA-Z0-9_]
- کاراکتر W\ که کاراکتر های به اصطلاح non-alphanumeric را که عکس مورد قبل می باشد را match می کند.
- کاراکتر d\ که اعداد ۰ تا ۹ را match می کند [9-0]
- کاراکتر D\ که کاراکتر های غیر از عدد را match می کند
- کاراکتر s\ که همان whitespace را match می کند
- کاراکتر S\ که non-whitespace یا عکس مورد بالا را match می کند
15. Lookarounds
دارای ۴ حالت زیر می باشد
- Positive Lookahead (?= )
- Negative Lookahead (?! )
- Positive Lookbehind (?<= )
- Negative Lookbehind (?<! )
حالت Positive Lookahead چک می کند که پترن داخل آن حتما باید بعد از پترنی که می خواهیم match کنیم قرار داشته باشد به معنای دیگر این ۴ حالت چک می کنند که پترنی که می خواهیم match کنیم باید بعد یا قبل شان یک پترن (داخل lookaround) وجود داشته باشد یا وجود نداشته باشد.
مثلا در (the(?=\sfat کلمه the فقط زمانی match می شود که بعد از آن حتما fat وجود داشته باشد.
"(T|t)he(?=\sfat)" => *The* fat cat sat on the mat.
حالت Negative Lookahead دقیقا برعکس حالت قبل می باشد و در مثال (the(?=\sfat فقط the را match می کند که بعد از آن کلمه fat نباشد.
"(T|t)he(?!\sfat)" => The fat cat sat on *the* mat.
حالت Positive Lookbehind چک می کند که قبل از پترنی که می خواهیم match کنیم حتما باید یک پترنی که با ( =>?) مشخص می شود پیش از آن وجود داشته باشد.
"(?<=(T|t)he\s)(fat|mat)" => The *fat* cat sat on the *mat*.
و حالت آخر یعنی Negative Lookbehind هم دقیقا برعکس حالت قبل می باشد و بدین معنی که قبل از پترنی که می خواهیم match کنیم پترن مشخص شده در داخل ( !>?) نباید وجود داشته باشد تا پترن ما match شود.
"(?<!(T|t)he\s)(cat|sat)" => The cat *sat* on the mat.
16. Flags
چندین کاراکتر یا در اصطلاح modifiers یا flag وجود دارند که برای کنترل کلی بر روی پترن های رگولار اکسپرشن می باشند.
- کاراکتر i : که به معنای Case insensitive می باشد
- کاراکتر g : که در اطلاح Global Search می باشد و به فارسی یعنی اینکه با پیدا کردن اولین match متوقف نشود و به دنبال موارد دیگر برای match کردن بگردد (به صورت پیش فرض regular expression اولین match ی که پیدا کند متوقف می شود)
- کاراکتر m : که به معنای Multiline می باشد
"/The/gi" => *The* fat cat sat on *the* mat.
سخن آخر
تلاش کردم که در این پست تقریبا اکثر کاراکترهای رگولار اکسپرشن را توضیح دهم و این موارد توضیح داده شده تقریبا کاراکتر های استانداردی هستند که در همه زبان ها یکسان هستند، ولی خب ممکنه در زبان های مختلف مواردی بیشتر از این ها را ببینید که کاربردهای بیشتری را به رگولار اکسپرشن اضافه کنند.
منابع
https://github.com/ziishaned/learn-regex/
مطلبی دیگر از این انتشارات
حیف از برکت نیست!؟
مطلبی دیگر از این انتشارات
ساخت پلاگین یونیتی برای لایبرری اندرویدی
مطلبی دیگر از این انتشارات
مشاهدهی لاگهای اپلیکیشن اندروید در لاگکت