عبارات باقاعده یا Regular Expression / قسمت اول

عبارت باقاعده در سکوی .NET Framework با نرم افزارExpresso
قبل از پرداختن به مفاهیم اصلی عبارت باقاعده و ذکر مثالها، توصیه می کنم ابتدا نرم افزار Expresso را که جهت تمرین و تست الگوهای عبارت باقاعده طراحی شده است، از نشانی http://www.ultrapico.com دانلود کنید. این نرم افزار با استفاده از کتابخانه های کلاسهای موجود در .NET Framework می تواند شما را در تولید الگوهای عبارات باقاعده و استفاده از آنها در برنامه هایتان یاری نماید. ضمن این که Expresso دارای یک سری الگوهای عبارات باقاعده از پیش نوشته شده است که شما را در دسترسی سریع و آسان به الگوی عبارت باقاعده مدنظرتان بسیاری یاری خواهد کرد.
یک مفهوم نام آشنا در بسیاری از سیستمهای کامپیوتری استفاده از کاراکترهای "جایگزین شونده" یا "wildcard" ها در الگوهای تطبیقی (pattren matching) می باشد. اگر شما قصد داشته باشید تمامی فایلهای Microsoft Word را در یکی از شاخه های ویندوز بیابید از عبارت "*.doc" ، برای جستجو استفاده خواهید کرد. علامت ستاره (astrisk) به عنوان یک wildcard ی که می تواند هر تعداد از کاراکترها را تطبیق دهد تفسیر خواهد شد.
در نوشتن برنامه هایا صفحات وبی که با رشته ها و متون زیاد سر و کله می زنند اکثر اوقات شما به چنین الگوهایی حتی با پیچیدگی بسیار بیشتری نیاز خواهید داشت. خوب عبارات باقاعده هم به همین منظور ابداع و تولید شده است. سکوی .NET Framework یک مجموعه کامل از کتابخانه کلاس هایی که کاربرد عبارات باقاعده را در برنامه های کاربردی آسان می سازد برای شما فراهم کرده است. با این کتابخانه شما می توانید به آسانی متنی را جستجو و جایگزین کنید، عنوان های پیچیده را رمزگشایی کنید، زبانهای مختلف را تجزیه کنید یا این که متنی را اعتبار سنجی نمایید.
بهترین روش برای یادگیری سینتکس اسرار آمیز عبارات باقاعده استفاده از مثالها و تجربه کردن آنها در برنامه های مختلف می باشد. این مقاله اصول اولیه عبارات باقاعده را به شما معرفی خواهد کرد و تعداد زیادی مثال را که در یک فایل کتابخانه Expresso قرار دارد به شما ارائه می دهد. اما اصل کاربرد این نرم افزار جهت آزمایش نمودن مثالها و نیز تست کردن صحت عملکرد عبارات باقاعده ای است که خودتان نوشته اید و قصد دارید در برنامه ها به کار گیرید. اگر اجازه بدهید شروع کنیم:

تعداد مثال ساده
قبل از این که به ارائه مثال ها بپردازم توجه شما را به این نکته جلب می کنم که در اکثر مثالهای ارائه شده در این مقاله می توانید از نمونه متن زیر جهت تست الگوهای ارائه شده اقدام کنید و توصیه می کنم قبل از این که توضیح الگو را بخوانید حتما الگوی ارائه شده و نمونه متن را در نرم افزار Expresso امتحان کرده و نتیجه را مشاهده کنید.

Tutorial Sample Data
Here is a space followed by backslash: " \"
Some people believe that Elvis is alive today.
It takes all kinds, I suppose. Elvis was sometimes
Known as "Elvis the Pelvis". Here is ELviS with
Weird capitalization.
Realistically, repeated words are easy to
to compose and hard to find.
The Queen of England visited Iraq and Qatar,
but she did not visit Quebec.
<body>Here is some text</body>
<p>A short paragraph</p>
aabab
SSN=
Phone numbers: 555-1212, 800 325-3535,
(650) 555-1212, (800) 325-3535, 650 555-1212
(650 555-1212.
Parentheses (ab(cd)ef) (g((hijk)l)m)n)o
SSN=123-45-6789
555-44-3333 42-33-7777
Zip=95070 55901-1234 90210 902101
IP Addresses: 123.456.789.012 255.243.190.101
12.1.34.2 12.1.34
Mississippi
One last phone number, filling the line.
555-1234

جستجوی کلمه Elvis
فرض کنیم شما مدت زمانی را در اسناد خود برای یافتن شواهدی که Elvis هنوز زنده است (alive) صرف کرده اید.

    Regular Expression
    elvis

    Sample Text and Search Results
    Some people believe that Elvis is alive today.
    It takes all kinds, I suppose. Elvis was sometimes
    Known as "Elvis the Pelvis". Here is ELviS with
    Weird capitalization.

    در این مثال RegexOptions.IgnoreCase فعال شده است. شما به آسانی می توانید با تنظیم گزینه ای (option) به معنای "چشم پوشی از بزرگ و کوچک بودن حروف" عبارتهایی مانند "ELVIS","Elvis","eLvIs"و . . . را نیز تطبیق دهید. ضمن این که شما می توانید به جای استفاده از RegexOptions.IgnoreCaseاز الگوی[Ee][Ll][Vv][Ii][Ss] برای یافتن هر شکل از کلمه elvis استفاده کنید. براکتهای باز و بسته "[" , "]" در بیشتر مواقع برای جستجوی عبارات بدون توجه به بزرگ و کوچک بودن حروف استفاده می شود. گزینه های مورد بحث در این سلسه مقالات در .NET Framework و در فضای نام System.Text.RegularExprssions و در مجموعه شمارشی RegexOptions قرار دارند. این گزینه ها را می توانید به صورت ترکیبی از OR های بیتی به سازنده کلاس  Regexدر فضای نام ذکر شده ارسال کرده و رفتار تطبیق الگوی خود را تغییر دهید. برای این مثال می توانید از سازنده زیر جهت ایجاد یک شی از کلاس Regex همراه با گزینه های مورد نظر استفاده کنید.

    Using System.Text.RegularExpressions;
    Regex rx=new Regex("elvis",RegexOptions.IgnoreCase|RegexOptions.CultureInvariant);

    کد فوق به زبان C#نوشته شده است. شما اگر از VB استفاده می کنید برای ارسال ترکیب بیتی گزینه به سازنده به جای علامت | می بایست از کلمه کلیدی OR استفاده کنید.
    متاسفانه الگوی elvis به تنهایی پنج حرف آخر کلمه "Pelvis" را نیز تطبیق داده است. برای جلوگیری ازاین حالت می بایست الگوی خود را به شکل زیر تغییر دهید:
    \belvis\b کلمهelvis را به عنوان یک کلمه کامل و جدا از سایر کلمات پس و پیش خود می یابد.

    Regular Expression
    \belvis\b

    Sample Text and Search Results
    Some people believe that Elvis is alive today.
    It takes all kinds, I suppose. Elvis was sometimes
    Known as "Elvis the Pelvis". Here is ELviS with
    Weird capitalization.

    حالا کمی جالبتر شد. "\b" یک کد به خصوص است. با معنای این که " موقعیت ابتدا یا انتهای هر کلمه (words boundary)یا مرز کلمات را تطبیق بده." این عبارت فقط عبارتهای "elvis" که به طور کامل و جدا از سایر حروف هستند و با هر ترکیبی از حروف بزرگ و کوچک یافته و تطبیق می دهد.
    تا به اینجا هنوز متوجه نشدیم که Elvis زنده هست یا خیر؟ برای یافتن پاسخ باید جستجو کنیم که آیا بعد از کلمه elvis کلمه alive (به معنی زنده) قرار دارد یا خیر. برای این کار می توانیم از الگوی زیر استفاده کنیم:
    \belvis\b.*\balive\b متنی را که دارای کمله elvis است و به دنبال آن کلمه alive آمده است جست جو می کند.

    Regular Expression
    \belvis\b.*\balive\b

    Sample Text and Search Results
    Some people believe that Elvis is alive today.
    It takes all kinds, I suppose. Elvis was sometimes
    Known as "Elvis the Pelvis". Here is ELviS with
    Weird capitalization.

    خوب الحمد الله Elvis هنوز زنده است. در الگوی فوق از یک کاراکتر نقطه "." (period or dot) استفاده کرده ایم. نقطه یک کد ویژه است و هر کاراکتری به جز خط جدید (new line-\n) را تطبیق می دهد. کاراکتر دیگری یکه در الگوی فوق به کار رفته است "*" است و به این معنای تکرار صفر یا بی نهایت عبارت یا کاراکتر قبل از خود است و می گوید " تضمین می کنم هر تعداد از عبارت پیش از خود که موجود باشد برای شما تطبیق  دهم." بنابراین ".*" به معنای تطبیق هر تعداد کاراکتر به غیر از کاراکتر خط جدید می باشد. ترکیب دو کاراکتر ".*" یک قالب ساده برای ایجاد یک عبارت باقاعده به مفهوم جستجوی هر چیزی به غیر از خط جدید بین دو کلمه elvis و alive است.
    یادداشت:
    شما می توانید با فعال کردن گزینه RegexOptions.Singleline  کاری کنید که "." بتواند حتی کاراکتر \n را نیز تطبیق دهد.
    در با فقط تعداد کمی کاراکتر خاص ما توانستیم شروع به ساخت عبارات باقاعده مفیدی کنیم. این در حالی است که قبلاً این کار برای ما بسیار سخت و دشوار می نمود. اجازه بدهید مثال دیگری را امتحان کنیم:
    فرض کنیم صفحه وب شما شماره تلفن های هفت رقمی مشتریان را گردآوری می کند و شما می خواهید تشخیص دهید که شماره تلفن وارده توسط مشتری درقالب صحیحی وارده شده است یا خیر. xxx-xxxx یک فرمت صحیح است که در آن  xیک عدد است. الگوی زیر کل متن را برای یافتن چنین رشته ای جستجو می کند:

    \b\d\d\d-\d\d\d\d

    شماره تلفن های هفت رقمی را پیدا می کند.

    Regular Expression
    \b\d\d\d-\d\d\d\d

    Sample Text and Search Results
    Phone numbers: 555-1212, 800 325-3535,
    650 555-1212, (800)325-3535, (650) 555-1212,
    650) 555-1212.
    Mississippi
    One last phone number, filling the line.
    555-1234

    هر "\d" به معنای تطبیق یک عدد تکت رقمی است. کاراکتر "-" معنای خاصی نداشته و به عنوان یک حرف عادی تفسیر شده و یک خط تیره را تطبیق می دهد.
    برای اجتناب از تکرارهای بی مورد و خسته کننده می توانیم از نمادگذاری هایی که جهت خلاصه نویسی مهیا شده اسند استفاده کنیم. در مورد این مثال می توانیم عبارت باقاعده زیر را به کار ببریم:

    Regular Expression
    \b\d{3}-\d{4}

    Sample Text and Search Results
    Phone numbers: 555-1212, 800 325-3535,
    650 555-1212, (800)325-3535, (650) 555-1212,
    650) 555-1212.
    Mississippi
    One last phone number, filling the line.
    555-1234

    نتیجه به دست آمده همان نتیجه مثال شماره 4 است. "{3}"یا"{4}" به همراه "\d" به معنای تکرار کاراکتر قبلی به تعداد دقیقاً سه یا چهار مرتبه است.
    به نظر رسیده که حالا نوبت این رسیده که بدانیم چگونه می توان صحت الگوهای خود را بیازماییم.
    تنبلی نکنید. نرم افزار Expresso را دانلود کنید و در سیستم خود نصب کنید. چون مطمئناً جهت آشنایی با عملکرد الگوهایی که به زبان عبارت باقاعده نوشته اید به یک نرم افزار تخصصی در این زمینه نیاز خواهید داشت.

    Expresso
    اگر شما اعتقاد دارید که یادگیری عبارات باقاعده دشوار نیست، فرض من بر این خواهد بود که شما شخصی بسیار باهوش هستید یا اینکه از سیاره ای دیگر به این کره آمده اید. سینتکس عبارات باقاعده می تواند هر شخصی را که به طور مکرر از عبارات باقاعده استفاده نمی کند گول بزند. این مسئله موجب ایجاد اشتباهات زیادی شده و باعث گردید به نظرم برسد که به یک ابزار ساده برای ایجاد و تست عبارات باقاعده نیاز است. چنین ابزاری بسیار زیادند ولی من طرفدار Expresso هستم. این نرم افزار رایگان می باشد. برای این که آخرین نسخه آنرا بتوانید در اختیار داشته باشید یک سر به سایت http://www.ultrapico.com بزنید. نسخه ای که در تصویر زیر می بینید مربوط به نسخه 2 است.
    شروع کنید. ابتدا Expresso را نصب کنید و Tutorial را از منوی Help انتخاب کنید و نحوه عملکرد نرم افزار و نیز سی نکته آموزشی موجود در آنرا مطالعه کنید. ضمناً شما می توانید هر موجودیتی در زبانه Expression Library را انتخاب و اجرا کرده و نتیجه را مشاهده کنید.
    Expresso مثال 5 را اجرا کرده است

    با انتخاب اولین مثال "1.Find Elvis" شروع کنید. سپس بروی Run Match کلیک کنید و نتیجه را در TreeView سمت راست ببینید. ملاحظه کنید که در قسمت ذکر شده چندین تطبیق وجود دارد. روی هر یک از آنها کلیک کنید. مکان دقیق تطبیق در متن نمونه را نشان می دهد. مثالهای دوم و سوم را نیز اجرا کنید. توجه داشته باشید که کلمه "Pelvis" جزء یافته های نمی باشد."\b" را از ابتدای عبارت باقاعده حذف کنید و توجه کنید یک قسمت از Zip Code (کدپستی) نیز به عنوان یک شماره تلفن تطبیق می یابد.

    اصول عبارت باقاعده در .NET Framework

    کاراکترهای خاص
    شما بایستی تعدادی با تعدادی از کاراکترهای خاص که معانی ویژه ای دارند، آشنا شوید.شما قبلا با "\b" , "." , "*" , "\d" آشنا شدید. برای تطبیق هر کاراکتر فضای خالی (whitespace) مانند space, tab و newlines از "\s" استفاده کنید."\w" هر کاراکتر کلمه و زیر خط را تطبیق می دهد و کاراکتر alphanumericنامیده می شود. برای یاد گیری بیشتر بهتر است چند مثال دیگر را مطرح کنیم:
    \ba\w*\b کلماتی که با حرف a شروع می شنود را می یابد.

    Regular Expression
    \ba\w*\b

    Sample Text and Search Results
    Try clicking the "Run Match" button (or F5) to see what
    happens. After a successful match click in the results box
    to highlight the matched text. Click the "Replace" button
    using the "Dates" example. Notice in the results box that the
    format of all the dates has been altered. Using the
    "Expression Library" tab double-click another regular
    expression and "Run Match".

    این الگو به دنبال حرف a که ابتدای آن "\b"(نشانه گذار کلمه) ، بعد از آن هر تعداد کاراکتر alphanumeric "\w*" و در انتهای آن "\b" باشد می گردد.
    \d+ رشته های عددی را تطبیق می دهد.

    Regular Expression
    \d+

    Sample Text and Search Results
    Netherlands Postal Codes:
    1234 ZA
    5678 KL5
    0123 AZ -> Illegal number, must be 1000-9999
    5432 ABQ -> Too many characters

    عملکرد کاراکتر خاص "+" همانند "*" است، با این تفاوت که نیاز به حداقل یک تکرار از عبارت قبل از خود را دارد.
    \b\w{6}\b کلمات شش کاراکتری را پیدا می کند.

    Regular Expression
    \b\w{6}\b

    Sample Text and Search Results
    Try clicking the "Run Match" button (or F5) to see what
    happens. After a successful match click in the results box
    to highlight the matched text. Click the "Replace" button
    using the "Dates" example. Notice in the results box that the
    format of all the dates has been altered. Using the
    "Expression Library" tab double-click another regular
    expression and "Run Match".
    Click "Show the Builder" (or Ctrl+D) to start designing your
    own regular expressions; or enter them directly in the
    regular expression box. Enter the text you want to search in
    the sample text box.
    Expand nodes in the "Regex Analyzer" to see a deion
    of the current regular expression. Right-click a node to edit
    the expression.

    این مثالها را در نرم افزار Expresso وارد کنید و با ایجاد عباراتی که خودتان می نویسید شروع به کار کنید و نترسید.
    در اینجا بعضی از کاراکترهای ویژه که معانی خاصی دارند را مشاهده می کنید:
    "."             هر کاراکتر به جز newline را تطبیق می دهد. درصورت استفاده از گزینه RegexOptions.Singleline ، کاراکتر نقطه می تواند کاراکتر newline را نیز تطبیق دهد.
    "\w"            هر کاراکتر کلمه را تطبیق می دهد.
    "\s"            هر کاراکتر فضای خالی را تطبیق می دهد.
    "\d"            یک رقم را تطبیق می دهد.
    "\d"            نشانه گذار کلمه که می تواند ابتدا و انتهای کلمه را تشخیص داده و آنرا تطبیق دهد.
    "^"             کاراکتر هشتک. این متاکاراکتر ابتدای رشته را تطبیق می دهد.
    "$"            کراکتر دلار. انتهای رشته را تطبیق می دهد.
    از ابتدا(In the beginning)
    متاکاراکترهای "^" و "$" وقتی که در جستجوی عبارتی هستید که در ابتدای متن آغاز شده و یا در انتهای متن به پایان رسیده است به کار می روند و نوعی تطبیق مکانی را برای شما انجام می دهند. این خاصیت وقتی که در نظر دارید کل متن ورودی را با الگوی عبارت باقاعده تطبیق دهید مفید واقع می شود. برای مثال اعتبار سنجی شماره تلفن های هفت رقمی ممکن است از الگوی زیر استفاده کنید:
    ^\d{3}-\d{4}$ شماره تلفن های هفت رقمی را اعتبار سنجی می کند.

    Regular Expression
    ^\d{3}-\d{4}$

    Sample Text and Search Results
    555-1212
    325-3535
    666-1212
    328-3838
    555-1234

    هیچ شماره تلفنی تطبیق داده نشد! زیرا شما می خواستید که کل رشته ورودی شما فقط متشکل از یک شماره تلفن باشد نه چند شماره. یعنی از ابتدا "^" رشته تا انتهای رشته "$" فقط یک الگوی "\d{3}-\d{4}" باشد که می تواند فرمتهای xxx-xxxx را تشخیص دهد باشد.

    Regular Expression
    ^\d{3}-\d{4}$

    Sample Text and Search Results
    555-1212

    شما می توانید با ارسال گزینه RegexOptions.MultiLine به سازنده کلاس Regex از دو متاکاراکتر "^" , "$" بخواهید به جای ابتدا و انتها رشته، ابتدا و انتهای خط را تطبیق دهند. در این صورت کلیه شماره تلفنهای زیر را می توان با استفاده از الگوی ذکر شده در مثال 9 تطبیق داد.

    Regular Expression
    ^\d{3}-\d{4}$

    Sample Text and Search Results
    555-1212
    325-3535
    666-1212
    328-3838
    555-1234