پنجشنبه ۲۸ تیر ۱۴۰۳

Thursday, July 18, 2024 GMT +3:30

آموزش کاربردی عبارات با قاعده (Regular Expressions)

web-regular-expressions

یکی از پیچیده ترین و در عین حال پرکاربردترین مباحث در زبان های برنامه نویسی و به طور خاص برنامه نویسی وب (PHP، JavaScript و...) بحث نحوه نوشتن و استفاده از دستورات عبارات با قاعده - Regular Expressions (به اختصار Regex یا Regexp) است، عبارات باقاعده یا منظم به توالی کاراکترهای خاص جهت ایجاد یک الگو (Pattern) مشخص گفته می شود که در موقعیت های مختلف برنامه نویسی مانند اعتبارسنجی ورودی ها یا پیدا کردن و جایگزینی مقادیرخاص در داده های متنی کاربرد دارند، برنامه نویس با تعریف یک الگوی معنی دار از عبارات باقاعده و درج آنها در توابع و متدهایی که می توانند این عبارات را درک کنند بخش خاصی از رشته متنی را استخراج یا تطابق رشته ورودی با الگوی مد نظر را بررسی می کند، به طور مثال در وب برای اعتبارسنجی صحت آدرس ایمیل ارسال شده از فرم ثبت نام می توانیم ورودی کاربر را با الگوی یک آدرس ایمیل کامل تطابق دهیم، البته نحوه نوشتن الگو و استفاده صحیح از کاراکترها در دستورات عبارات باقاعده حداقل در مرحله شروع آموزش Regex پیچیدگی هایی دارد که در مطلب پیش رو سعی کرده ایم در حد امکان مختصرو مفید همراه با مثال های کاربردی مباحث را ساده و قابل درک بیان کنیم.

مفهوم عبارات با قاعده (Regular Expressions)


اگر بخواهیم یک تعریف مختصر از عبارات با قاعده - Regular Expressions (به اختصار Regex یا Regexp) در دنیای کامپیوتر و برنامه نویسی ارائه کنیم، می توان گفت روش ها و قواعدی مبتنی بر تعریف الگوی متنی از توالی کاراکترها هستند که برای استخراج یا بررسی وجود یک مقدار (عددی، متنی و...) در رشته متنی مد نظر به کار می روند، در واقع این قواعد بر مبنای اصول خاص بخش بخصوصی از یک رشته متنی یا عددی را با توجه به هدف و الگوی تعریف شده ما بررسی یا استخراج می کنند که در محاسبات دقیق والگوریتم های پیچیده بسیار کاربردی خواهد بود، استفاده از عبارات با قاعده معمولا در چارچوب های مشخصی که توانایی پردازش آنها را داشته باشند انجام می شود، به طور مثال در توابع خاص زبان های برنامه نویسی، دستورات htaccess، قسمت جستجو و جایگزینی (Find & Replace) برنامه هایی که از این قواعد پشتیبانی می کنند و...، به عبارت دیگر صرف قرار دادن مستقیم کاراکترها در بخش های مختلف کدهای برنامه نتیجه خاصی ندارد.

عبارات با قاعده چگونه نوشته می شوند؟


پس از آشنایی با مفهوم Regular Expressions، سوالی که به ذهن می رسد این است که عبارات با قاعده چگونه نوشته می شوند؟ در پاسخ باید گفت که دستورات در این روش از طریق توالی علامت ها، کلمات، حروف یا کاراکترهای خاصی (مانند [] () + \ *? | , w \W\ 0-9 a-z و...) که هر کدام مفهوم ویژه ای دارند، تعریف می شوند، در واقع از کنار هم قرار گرفتن این علامت ها، دستور ویژه ای شکل گرفته و قسمت خاصی از رشته مورد نظر استخراج یا بررسی می شود، چند مثال کاربردی:
- بررسی وجود یک کلمه خاص در یک رشته متنی در PHP
فرض کنید می خواهیم وجود کلمه php را در متن "php is easy and powerful" بررسی کنیم، در این صورت با استفاده از تابع preg_match خواهیم نوشت:
<?php
$str = 'php is easy and powerful';
echo preg_match('/php/', $str);
?>
خروجی کد بالا برابر با 1 خواهد بود، البته 1 در اینجا یعنی کلمه مورد نظر در عبارت وجود دارد (1 معادل TRUE است)، حال اگر کلمه php را با حروف بزرگ در دستور بالا قرار دهیم، نتیجه صفر خواهد بود، مگر اینکه یک کاراکتر با قاعده (در ادامه خواهیم دید که این کاراکتر را modifier یا تغییر دهنده می نامند) دیگر به دستورمان اضافه کنیم که بزرگ یا کوچک بودن حروف را نادیده بگیرد، این کاراکتر حرف i به معنی incasesensitive یا غیر حساس به حروف بزرگ و کوچک است:
<?php
$str = 'php is easy and powerful';
//echo preg_match('/PHP/', $str); //نتیجه 0 خواهد بود
echo preg_match('/PHP/i', $str); //نتیجه 1 خواهد بود
?>
- بررسی یک رشته متنی برای حرف a-z و اعداد 0-9 در JavaScript
در این مثال می خواهیم رشته متنی را در JavaScript بررسی کنیم و ببینیم آیا تنها شامل حروف a-z، اعداد 0-9 و فضای خالی است یا خیر، خواهیم نوشت:
<script type="text/javascript">
var str = 'Regex is so Simple!!';
var reg = /^[0-9A-Za-z ]*$/;
if(reg.test(str)){
    alert('مقادیر معتبر است');
}
else{
    alert('مقادیر معتبر نیست');    
}
</script>
کد بالا پیام "مقادیر معتبر نیست" را نمایش خواهد داد، دلیل آن وجود دو علامت !! در رشته متنی است، برای اینکه کاراکترهای مجاز بیشتری به مقایسه عبارات با قاعده اضافه کنیم، کد بالا را به شکل نمونه زیر تغییر می دهیم:
<script type="text/javascript">
var str = 'Regex is so Simple!!';
var reg = /^[0-9A-Za-z!&@\.\$%\\\-,\(\):;` ]*$/;
if(reg.test(str)){
    alert('مقادیر معتبر است');
}
else{
    alert('مقادیر معتبر نیست');    
}
</script>
نکته: در دستورات چند کاراکتر خاص مانند ^، $، *، + و... را ملاحظه می کنید که در ادامه به صورت جزئی تر در مورد آنها خواهیم گفت.
- نوشتن یک RewriteRule در htaccess
فرض کنید لینک داینامیکی به صورت index.php?user=2740 داریم که می خواهیم با استفاده از mod rewrite در htaccess آن را به صورت user/2740 دریافت کنیم، در این صورت در فایل htaccess خواهیم نوشت:
RewriteEngine On
RewriteRule ^user/([0-9]+) /index.php?user=$1 [NC,L]
ملاحظه می کنید که در اینجا نیز عبارات با قاعده بسیار کاربرد دارند.

مفهوم و کاربرد کاراکترهای دستورات با قاعده


همان طور که دیدیم، دستورات در عبارات با قاعده با استفاده از حروف و کاراکترهای خاصی که در صفحه کلید کامپیوترمان وجود دارد نوشته می شوند، اما مسلما بدون رعایت اصول خاص (syntax) و درک مفهوم این کاراکترها، عملا از نوشتن یا تفسیر صحیح این دستورات ناتوان خواهیم بود، لذا در ادامه به صورت موردی با این موارد و کاربرد آنها آشنا خواهیم شد.

حروف (لاتین)


اولین و ساده ترین مواد اولیه ای که در یک دستور Regex به کارمان می آید حروف ...abcd هستند، یعنی با قرار دادن آنها در یک دستور با قاعده، توالی از رشته متنی که شامل این کاراکترها باشد، انتخاب می شود، مثال:
<?php
$str = 'abcdefg';
$check = preg_match('/abc/', $str);
echo $check;
?>
خروجی کد بالا عدد 1 خواهد بود، چون توالی عبارت abc در رشته abcdefg وجود دارد.
نکته: الزامی به رعایت ترتیب الفبایی نیست، مهم این است که توالی قسمت Regex در رشته متنی وجود داشته باشد.

اعداد


اعداد 0 تا 9 و ترکیب آنها، دومین موادی است که می توانیم در یک دستور با قاعده از آنها استفاده کنیم، کاربرد ساده این کاراکترها مانند مثالی است که پیش تر ملاحظه کردیم:
<?php
$str = '314276539';
$check = preg_match('/427/', $str);
echo $check;
?>
که خروجی برابر 1 خواهد بود.

کاراکتر . (هر کاراکتری)


کاراکتر بعدی که در عبارات با قاعده کاربرد دارد، نقطه یا dot است که به معنی هر کاراکتری (به جزء خط جدید) است، به طور مثال:
<?php
$str = 'Regex is not too difficult!';
$check = preg_match('/Re.ex/', $str);
echo $check;
?>
خروجی کد بالا عدد 1 خواهد بود، اگرچه ما در دستور با قاعده از عبارت Re.ex استفاده کرده ایم، اما همان طور که گفتیم، نقطه در این دستورات شامل هر کاراکتری (به جزء خط جدید) می شود.
نکته: زمانی که بخواهیم کاراکتر نقطه از حالت دستوری (یعنی حالتی که شامل همه کاراکترها می شود) خارج و صرفا در نقش یک حرف (در نقش نقطه یا به اصطلاح literal) ظاهر شود، باید با یک بک اسلش (\) آن را درج کنیم، به این صورت اثر آن به عنوان یک کاراکتر دستوری از دست می رود، مثال:
<?php
$str = 'Regex is not too difficult!';
$check = preg_match('/Re\.ex/', $str);
echo $check;
?>
که کد بالا خروجی 0 را چاپ می کند، چون .\ تنها شامل خود نقطه می شود نه کاراکتر دیگری (به عبارت دیگر اگر در رشته متنی، Regex برابر Re.ex بود، بررسی بالا عدد 1 را چاپ می کرد).

کاراکتر [ ] (دست کم یک کاراکتر)


قلاب، کروشه یا bracket کاراکتر دیگری است که در دستورات با قاعده بسیار کاربرد دارد، این کاراکتر در حالت دستوری جزء علامت های محدود ساز است و تنها کاراکترهای خودش را شامل می شود (در حالت عادی حساس به حروف بزرگ و کوچک)، به فرض [a] تنها شامل رشته ای می شود که دست کم حرف a در آن به کار رفته باشد، چند نمونه از کاربرد این علامت:
[a] - شامل رشته ای می شود که دست کم a در آن به کار رفته باشد، مانند abcd، bacd، aaab و... (به طور مثال شامل bcd، 123، bbbb و... نمی شود).
[zxn] - شامل رشته ای می شود که دست کم z یا x یا n در آن به کار رفته باشد، مانند zxn، regex، zend و... (به طور مثال شامل ZXN، abc، 123 و... نمی شود).
[a-z] - شامل رشته ای می شود که دست کم حروف a تا z (الفبای انگلیسی با حروف کوچک) در آن به کار رفته باشد، مانند Php، javascript، Bbbb و... (به طور مثال شامل 1@2،  JAVASCRIPT، 123 و... نمی شود).
[A-Z] - شامل رشته ای می شود که دست کم حروف A تا Z (الفبای انگلیسی با حروف بزرگ) در آن به کار رفته باشد، مانند PHP، JavaScript، BBBB و... (به طور مثال شامل abc، 123، aa و... نمی شود).
[0-9] - شامل رشته ای می شود که دست کم اعداد 0 تا 9 در آن به کار رفته باشد، مانند 49CC، 222، b123 و... (به طور مثال شامل abcd، p%@&*، aa و... نمی شود).
[abct-z] - شامل رشته ای می شود که دست کم حرف a یا b یا c یا t تا z در آن به کار رفته باشد (دقت کنید که در اینجا چون توالی حروف انگلیسی بهم خورده است، علامت - از حرف t به بعد را شامل می شود)، مانند You، bb، abc و... (به طور مثال شامل Yo، 142، de و... نمی شود).
نکته 1: همان طور که در دستورات بالا ملاحظه کردید، علامت - یک کاراکتر همراهی کننده در عبارات با قاعده (یعنی در کنار سایر علامت ها استفاده می شود) و به معنی "تا" است.
نکته 2: علامت - در صورتی که در ابتدا یا انتهای دستور قرار گیرد، خاصیت دستوری خود را از دست می دهد، به طور مثال [az-] شامل a یا z یا علامت - می شود (همچنین [-az]).
نکته 3: علامت [ یا ] چنانچه بلافاصله بعد از اولین قلاب قرار گیرد، حالت دستوری خود را از دست می دهد، به طور مثال [zxn[] شامل z یا x یا n و یا علامت [ می شود.

کاراکتر [ ^] (به جزء کاراکتر)


در کنار کاراکتر قلاب، کاراکتر قلاب و علامت ^ وجود دارد که برعکس حالت معمول، به معنی هر کاراکتری به جزء آنچه درون قلاب تعریف شده است می باشد، به فرض [a^] شامل رشته ای می شود که به جزء حرف a، کاراکتر دیگری در آن باشد (اگر تنها حرف a باشد، نتیجه FALSE خواهد بود)، یا [acd^] شامل رشته ای می شود که به جزء حروف a و c و d، کاراکتر دیگری نیز داشته باشد، به چند مثال توجه کنید:
[a^] - شامل رشته ای می شود که به جزء a، کاراکتر دیگری در آن به کار رفته باشد، مانند abcd، bacd، aaab و... (به طور مثال شامل aaaa، a، aa و... نمی شود).
[zxn^] - شامل رشته ای می شود که به جزء z و x و n، کاراکتر دیگری در آن به کار رفته باشد، مانند ZXN، regex، zend و... (به طور مثال شامل zxn، xnnn، zzz و... نمی شود).
[a-z^] - شامل رشته ای می شود که به جزء حروف a تا z (الفبای انگلیسی با حروف کوچک)، کاراکتر دیگری در آن به کار رفته باشد، مانند Php، Javascript، bbbb1 و... (به طور مثال شامل php، javascript، bbbb و... نمی شود).
[A-Z^] - شامل رشته ای می شود که به جزء حروف A تا Z (الفبای انگلیسی با حروف بزرگ)، کاراکتر دیگری در آن به کار رفته باشد، مانند Php، JavaScript، BBBb و... (به طور مثال شامل PHP، JAVASCRIPT، BBBB و... نمی شود).
[0-9^] - شامل رشته ای می شود که به جزء اعداد 0 تا 9، کاراکتر دیگری در آن به کار رفته باشد، مانند 49CC، 22%، b123 و... (به طور مثال شامل 000، 222، 123 و... نمی شود).
[abct-z^] - شامل رشته ای می شود که به جزء حرف a و b و c و t تا z (با حروف کوچک)، کاراکتر دیگری در آن به کار رفته باشد، مانند You، b&b، ab1c و... (به طور مثال شامل u، bb، abc و... نمی شود).
نکته: به حساس بودن دستورات به حروف بزرگ و کوچک دقت کنید.

کاراکتر ^ (شروع)


علاوه بر استفاده از کاراکتر ^ (hat) در درون قلاب، این کاراکتر به تنهایی نیز در دستورات مربوط به عبارات با قاعده کاربرد فراوان دارد، علامت ^ (خارج از قلاب و در شروع دستور) به معنی نقطه شروع یک رشته است، به طور مثال دستور bcd^ به معنی هر عبارتی است که از ابتدا با bcd شروع شده باشد، لذا رشته bcde را شامل می شود، اما abcd را خیر (چون عبارت اول دقیقا با bcd شروع شده اما عبارت دوم با abc)، چند مثال:
<?php
$str = 'php is easy and powerful!';
$check = preg_match('/^php/', $str);
echo $check;
?>
خروجی دستور بالا برابر 1 یا TRUE خواهد بود، چون عبارت دقیقا با php شروع شده، اما اگر مثال به صورت زیر بود:
<?php
$str = 'why php is easy and powerful?!';
$check = preg_match('/^php/', $str);
echo $check;
?>
خروجی برابر 0 یا FALSE خواهد بود، چون در دستور تنها رشته ای را در نظر گرفته ایم که از شروع با عبارت php باشد، در حالی که شروع رشته ما با عبارت فرضی why است.
نکته: همان طور که پیش از این ملاحظه کردید، کاربرد علامت ^ درون قلاب با حالت عادی متفاوت است.

کاراکتر $ (پایان)


در کنار علامت ^ (نقطه شروع رشته)، از علامت $ (dollar) برای تعیین نقطه پایان یک عبارت استفاده می شود، به طور مثال دستور $bcd به معنی هر عبارتی است که در انتها به bcd ختم شود، لذا رشته abcd را شامل می شود، اما bcde را خیر (چون عبارت اول دقیقا به bcd ختم شده اما عبارت دوم به cde)، چند مثال:
<?php
$str = 'PHP for Web';
$check = preg_match('/Web$/', $str);
echo $check;
?>
خروجی دستورات بالا عدد 1 خواهد بود، چون رشته مورد بررسی ما دقیقا به عبارت Web ختم شده، اما اگر رشته به صورت فرضی زیر بود:
<?php
$str = 'PHP for Web?!';
$check = preg_match('/Web$/', $str);
echo $check;
?>
نتیجه برابر 0 می شد، چون عبارت به web ختم نشده بلکه به علامت ?! ختم شده است.
نکته: در کدنویسی حرفه ای و پیشرفته، معمولا از ترکیب پیچده تری از این دستورات ساده استفاده می شود، اما قواعد و اصول کار به همین صورت است.

کاراکتر { } (تعداد تکرار)


در دستورات عبارات با قاعده از علامت {} (آکولاد یا brace) برای مشخص کردن تعداد تکرار یک کاراکتر استفاده می شود، به طور مثال {3}a شامل عبارتی می شود که a در آن سه بار به صورت متوالی تکرار شده باشد، به فرض aaa، عدد داخل {} اگر به صورت تکی باشد، نمایانگر تعداد حداقل تکرار متوالی است، به فرض {5} یعنی الزاما باید حداقل 5 بار متوالی یک کاراکتر تکرار شده باشد، اما اگر به صورت دو قسمتی باشد (به طور مثال {1,3})، عدد اول حداقل تکرار و عدد دوم حداکثر را نشان می دهد، یعنی حداقل 1 بار و حداکثر سه بار تکرار را شامل می شود، به مثال زیر توجه کنید:
<?php
$str = 'bbb';
$check = preg_match('/^b{1,3}$/', $str);
echo $check;
?>
خروجی مثال بالا عدد 1 خواهد بود، چون رشته با حرف b شروع شده، حرف b از یک تا سه بار در آن تکرار شده و نهایتا نیز به b ختم شده، اما اگر همین دستور را به شکل زیر تغییر دهیم:
<?php
$str = 'bbbb';
$check = preg_match('/^b{1,3}$/', $str);
echo $check;
?>
نتیجه برابر 0 خواهد بود، چرا که حرف b چهار بار متوالی در رشته تکرار شده، در حالی که در دستور ما 1,3 بار مد نظر است.
دقت کنید که علامت {} در حالت عادی تنها یک کاراکتر یا مجموعه ای از کاراکترهای قبل از خود را بررسی می کند، به طور مثال در دستور {1,3}web، تنها تکرار حرف b مورد نظر است، نه کل عبارت، به مثال زیر توجه کنید:
<?php
$str = 'webbbb';
$check = preg_match('/^web{1,3}$/', $str);
echo $check;
?>
نتیجه دستور بالا 0 یا FALSE خواهد بود، چون تکرار حرف b بین یک تا سه بار مد نظر است، اما این حرف چهار بار متوالی در رشته مورد بررسی تکرار شده است.
نکته: تعین عدد دوم در برخی زبان های برنامه نویسی مانند JavaScript اختیاری است، لذا اگر به فرض دستور را به شکل {,1}web استفاده کنید، یعنی حداقل یک و حداکثر هر تعدادی را شامل می شود (حداکثری ندارد)، مثال:
<script type="text/javascript">
var str = 'webbbb';
var reg = /^web{1,}$/;
if(reg.test(str)){
    alert('مقادیر معتبر است');
}
else{
    alert('مقادیر معتبر نیست');    
}
</script>
که پیغام "مقادیر معتبر است" را نمایش خواهد داد، چون حداکثر تکرار را تعیین نکرده ایم.

کاراکتر * (صفر تکرار یا بیشتر)


علامت * (star یا ستاره)، کاراکتر دیگری است که در عبارات با قاعده کاربرد دارد، این کاراکتر به معنی صفر تکرار یا بیشتر است، به طور مثال  *a شامل رشته ای می شود که حرف a در آن صفر بار یا به دفعات بیشتری تکرار شده باشد، یا به طور مثال دستور *ab^ شامل رشته ای می شود که با a شروع شده و حرف b در آن صفر بار یا بیشتر تکرار شده باشد، به مثال زیر توجه کنید.
<?php
$str = 'book';
$check = preg_match('/[ab]c*/', $str);
echo $check;
?>
خروجی دستور بالا برابر 1 خواهد بود، چون [ab] یعنی یا حرف a یا حرف b در رشته باشد، و در قسمت دوم دستور نیز صفر تکرار یا بیشتر حرف c مد نظر بوده که عملا تاثیری در عبارت با قاعده ما ندارد، اما اگر همین دستور به صورت زیر بود:
<?php
$str = 'book';
$check = preg_match('/[ad]c*/', $str);
echo $check;
?>
نتیجه برابر 0 یا FALSE خواهد بود، چون در قسمت اول دستور یعنی [ad]، وجود کاراکتر a یا d در رشته مد نظر است، اما چنین کاراکترهایی در book وجود ندارد.

کاراکتر + (یک تکرار یا بیشتر)


علامت + (plus یا به اضافه)، کاربردی مشابه * دارد،  با این تفاوت که در اینجا حداقل یک بار تکرار نیاز است، به عبارت دیگر این علامت نمایانگر یک بار تکرار یا بیشتر است، به طور مثال +a شامل رشته ای می شود که حداقل یک a در آن وجود داشته باشد، یا +550 شامل عددی می شود که حداقل یک صفر در آن به کار رفته باشد، به مثال زیر توجه کنید.
<?php
$str = 'web.a.55';
$check = preg_match('/^[a-z]{3}\.[abc]+\.[0-9]{1}/', $str);
echo $check;
?>
خروجی کد بالا 1 یا TRUE خواهد بود، چون بر طبق دستور مد نظر ما، رشته باید با a-z به تعداد 3 کاراکتر شروع شده، سپس یک نقطه داشته باشد و بعد از نقطه، یک یا بیشتر کاراکتر a یا b یا c داشته باشد، سپس یک نقطه و در نهایت به عدد 0 تا 9 برسد (چون از علامت $ استفاده نکرده ایم، مابقی رشته بررسی نمی شود)، اما اگر علامت $ را در انتهای دستور بالا اضافه کنیم، نتیجه 0 یا FALSE خواهد بود، چون تعداد 1 عدد در انتها مد نظر ما است، اما 55 شامل دو عدد است.

کاراکتر ? (اختیاری)


علامت ? (question mark یا سوال) در عبارات با قاعده کاربرد به خصوصی دارد، از این نشان برای اختیاری (optional) کردن کاراکتر قبل از آن استفاده می شود، به طور مثال jpe?g هم شامل jpg می شود و هم شامل jpeg، چون بعد از حرف e علامت ? قرار گرفته و لذا بود یا نبود این حرف اختیاری است، به مثال زیر توجه کنید.
فرض کنید آدرس فایلی به صورت زیر است:
../upload/image.jpg
اکنون می خواهیم نام فایل را بدون پسوند از آدرس بالا استخراج کنیم، بدین منظور پارامتر دومی به تابع preg_match اضافه کرده و Regex زیر را می نویسیم.
^\.\.\/upload\/(.*)\.jpe?g$
شکل کامل کد ما به صورت زیر خواهد بود.
<?php
$str = '../upload/image.jpg';
$check = preg_match('/^\.\.\/upload\/(.*)\.jpe?g$/', $str, $match);
echo $check;
print_r($match);
//echo $match[1];
?>
خروجی قسمت echo کد بالا عدد 1 یا مقادیر Boolean آن برابر TRUE خواهد بود، اما اگر با print_r از متغیر match (که خروجی تابع preg_match به صورت یک آرایه است) خروجی بگیریم، نتیجه به شکل زیر خواهد بود.
Array
(
    [0] => ../upload/image.jpg
    [1] => image
)
نکته 1: در عبارت با قاعده بالا، کاراکتر جدید () به کار رفته که در ادامه در مورد آن خواهیم گفت.
نکته 2: به عملکرد خنثی سازی علامت \ توجه کنید (برای خارج کردن کاراکتر . و / از حالت دستوری، از \ استفاده شده).

کاراکتر ( ) (ساخت گروه)


اگرچه علامت () (parenthesis یا پرانتز) در کاربردهای عادی مفهوم مشخصی دارد، اما این علامت در عبارات با قاعده طور دیگری تفسیر می شود و نمایانگر گروهی از توالی ها (pattern) است، به زبان ساده هر آنچه در بین () قرار گیرد به عنوان یک مجموعه دستور قابل استفاده است که در برخی توابع و دستورات به کار می رود، به طور مثال کد زیر در حالت عادی برای کلید 1 آرایه match چیزی چاپ نمی کند:
<?php
$str = 'image22.jpg';
$check = preg_match('/[a-z]+[0-9]*\.jpe?g$/', $str, $match);
echo $check;
print_r($match);
//echo $match[1];
?>
نتیجه قسمت print_r کد بالا:
Array
(
    [0] => image22.jpg
)
اما اگر همین کد را به صورت زیر ویرایش کنیم:
<?php
$str = 'image22.jpg';
$check = preg_match('/([a-z]+[0-9]*)\.jpe?g$/', $str, $match);
echo $check;
print_r($match);
//echo $match[1];
?>
خروجی قسمت print_r به صورت زیر خواهد بود:
Array
(
    [0] => image22.jpg
    [1] => image22
)
ملاحظه می کنید که دستورات داخل () به عنوان یک گروه خاص پردازش شده و نتیجه در یک کلید مجزا به خروجی ارسال شده است.
حال فرض کنید می خواهیم عدد 22 را نیز در یک کلید مجزا داشته باشیم، در این صورت از علامت () در داخل علامت () دیگر به صورت زیر گروه استفاده می کنیم:
<?php
$str = 'image22.jpg';
$check = preg_match('/([a-z]+([0-9]*))\.jpe?g$/', $str, $match);
echo $check;
print_r($match);
//echo $match[1];
?>
خروجی قسمت print_r به صورت زیر خواهد بود:
Array
(
    [0] => image22.jpg
    [1] => image22
    [2] => 22
)

کاراکتر | (یا)


اگر خاطرتان باشد گفتیم که علامت - در دستورات با قاعده به معنی "تا" است، حال می خواهیم علامت دیگری را معرفی کنیم که به معنی "یا" است، به طور مثال a|b یعنی یا a یا b، به مثال زیر توجه کنید.
<?php
$str = 'Iran is a beautiful country.';
$check = preg_match('/Iran|Tajikistan/', $str, $match);
echo $match[0]
?>
خروجی مثال بالا Iran خواهد بود، با توجه به دستور Regex اگر به جای Iran عبارت Tajikistan نیز وجود داشت، دستور معتبر بود و Tajikistan به عنوان خروجی چاپ می شد.

حروف خاص در عبارات با قاعده


تا این قسمت از آموزش، با کاراکترهای پرکاربرد در دستورات Regular Expressions آشنا شدیم، اما بخشی از مفاهیم این زبان جالب با استفاده از حروف خاصی تعریف می شود که در زیر به صورت تیتروار، لیست برخی از پر کاربردترین آنها را به همراه مثال با هم مرور می کنیم.

حرف d\


حرف d\ (حروف کوچک) به معنی هر عددی (d مخفف digit)، مثال:
<?php
$str = 'tel: +98';
$check = preg_match('/^tel: \+(\d+)/', $str, $match);
print_r($match);
?>
خروجی:
Array
(
    [0] => tel: +98
    [1] => 98
)
نکته 1: پیش تر گفتیم که علامت \ کاراکترهای دستوری را به حالت عادی تبدیل می کند، اما در اینجا برعکس حالت قبل، علامت \ کاراکترهای عادی را به دستور تبدیل می کند (d یک حرف عادی است، اما d\ یعنی هر عددی).
نکته 2: بزرگ یا کوچک بودن حروف خاص در عبارات با قاعده، ممکن است بر روی مفهوم آنها اثرگذار باشد.

حرف D\


حرف D\ (حروف بزرگ) به معنی هر کاراکتری که عدد نباشد، مثال:
<?php
$str = 'tel: +98W50';
$check = preg_match('/^tel: \+.*(\D+).*/', $str, $match);
print_r($match);
?>
خروجی:
Array
(
    [0] => tel: +98W50
    [1] => W
)
نکته: تمام مثال ها فرضی و صرفا جهت درک راحت تر مطالب ارائه شده اند، لذا ممکن است برخی مواقع عادی به نظر نرسند!

حرف w\


حرف w\ به معنی هر حرف الفبایی (لاتین)، مثال:
<?php
$str = 'your@email.com';
$check = preg_match('/^(\w+)@.+\.[a-z]{2,3}/', $str, $match);
print_r($match);
?>
خروجی:
Array
(
    [0] => your@email.com
    [1] => your
)

حرف W\


حرف W\ به معنی هر کاراکتری که حرف الفبایی یا عدد نباشد، مثال:
<?php
$str = 'P21#W@RR^';
$check = preg_match('/.*(\W+).*(\W+).*(\W+)/', $str, $match);
print_r($match);
?>
خروجی:
Array
(
    [0] => P21#W@RR^
    [1] => #
    [2] => @
    [3] => ^
)

حرف s\


حرف s\ به معنی هر فضای خالی (Whitespace)، مثال:
<?php
$str = 'Hello World!';
$check = preg_match('/(\w){1}.*\s(\w){1}.*/', $str, $match);
print_r($match);
?>
خروجی:
Array
(
    [0] => Hello World!
    [1] => H
    [2] => W
)

حرف S\


حرف S\ به معنی هر کاراکتری که فضای خالی نباشد، مثال:
<?php
$str = 'Hello World!';
$check = preg_match('/(\S+)\s(\S+)/', $str, $match);
print_r($match);
?>
خروجی:
Array
(
    [0] => Hello World!
    [1] => Hello
    [2] => World!
)

Modifiers در Regular Expressions


اگر به نکاتی که در خلال آموزش به صورت پراکنده به آن اشاره شد، توجه کرده باشید، سه مورد در کدهایی که تا این لحظه نوشتیم خودنمایی می کند:
- کدها به حروف بزرگ یا کوچک حساس هستند، به طور مثال [a-z] الزاما شامل حروف کوچک می شود.
- دستور . (هر کاراکتری) شامل خط جدید (line break) نمی شود، به طور مثال کد زیر عدد 0 یا FALSE را برمی گرداند:
<?php
$str = 'Reg
ex is not too difficult!'
;
$check = preg_match('/Re.ex/', $str);
echo $check;
?>
مشکل از آنجا نشات می گیرد که مقادیر متغیر فرضی str با یک خط جدید شکسته شده.
- اگر بخواهیم با علامت های ^ و $، ابتدا و انتهای رشته را مشخص کنیم، در حالتی که مقادیر رشته از چندین خط جدید تشکیل شده باشد، به مشکل بر خواهیم خورد.
راه حل مشکلات بالا در دستورات با قاعده، استفاده از تغییر دهنده ها یا Modifiers است، Modifiers چیزی نیستند جزء چند حرف خاص که در انتهای دستور قرار می گیرند و رفتار آن را تغییر می دهند.

modifier i


برای نادیده گرفتن بزرگ یا کوچک بودن حروف، از تغییر دهنده i (برگرفته از case-insensitive) استفاده می کنیم، به طور مثال:
<?php
$str = 'Hello World!';
$check = preg_match('/[a-z\s\W]*/i', $str, $match);
print_r($match);
?>
خروجی:
Array
(
    [0] => Hello World!
)

modifier s


برای محاسبه خط جدید در هنگامی که از کاراکتر دستوری . استفاده می کنیم، تغییر دهنده s (برگرفته از single line) کاربرد دارد، مثال:
<?php
$str = 'Reg
ex is not too difficult!'
;
$check = preg_match('/Re.+ex/s', $str);
echo $check;
?>
خروجی برابر 1 یا TRUE خواهد بود.
نکته: در این حالت خود خط جدید نیز یک کاراکتر محسوب شده، لذا درج علامت + (یک تکرار یا بیشتر) بعد از . ضرورت دارد.

modifier m


برای اعمال دستورات عبارات باقاعده به صورت خط به خط، تغییر دهنده m (برگرفته از multiline) کاربرد دارد، به عبارتی استفاده از این تغییر دهنده باعث می شود تا دستور ما در رشته هدف، به جای بررسی عادی، برای هر خط به صورت جداگانه بررسی شود، مثال:
<?php
$str = 'CSS
JavaScript
PHP
HTML
MySQL'
;
$check = preg_match('/^(HTML)/m', $str, $match);
print_r($match);
?>
خروجی:
Array
(
    [0] => HTML
    [1] => HTML
)
اما اگر همین کد را بدون m استفاده کنیم، نتیجه ای نخواهیم داشت:
<?php
$str = 'CSS
JavaScript
PHP
HTML
MySQL'
;
$check = preg_match('/^(HTML)/', $str, $match);
print_r($match);
?>
خروجی:
Array
(
)
نکته: منظور از خط، در واقع همان کاراکتر (نامرئی) n\ یا r\ است.
در پایان این آموزش باید یادآور شویم که دستورات مربوط به عبارات با قاعده به موارد گفته شده محدود نمی شوند، اما برای برنامه نویسی وب دانستن همین اصول و مفاهیم پر کاربرد، لازم و تا حد زیادی کافی خواهد بود.
دسته بندی: مهارتهای وب » دانستنی ها
related مطالب بیشتر:
اصطلاحات و مفاهیمی که مدیر سایت باید بداند!
چگونه با برنامه Outlook ایمیل ارسال و دریافت کنیم؟
حمله DDoS چیست و چگونه از آن جلوگیری کنیم؟
لیست کدهای وضعیت HTTP و معنی خطاهای سرور
مفهوم پلتفرم (Platform) و فریم ورک (Framework)
دیدگاه
more ۱۵۳ دیدگاه برای این مطلب ارسال شده است.
more دیدگاه جدید بر اساس تاریخ ارسال در انتهای دیدگاه های موجود نمایش داده می شود.
امیرحسین
۱۵:۱۳ ۱۳۹۶/۰۵/۰۴
سلام استاد عزیز واقعا ممنون نمیدونم چطوری تشکر کنم خیلی مفید بود برام تشکر
۲۳:۵۴ ۱۳۹۶/۱۱/۱۲
مطلب فوق العاده ای بود
خیلی ساده و کامل توضیح دادید
خیلی ممنون
امیرحسین
۱۸:۱۲ ۱۳۹۷/۰۴/۲۶
سلام استاد امیدوارم حال شما خوب باشه
من دارم یه سیستم وبلاگ دهی درست میکنم واسه درس پروژه دانشگاه که مهلت زیادی هم ندارم فقط یه قسمتش گیر کردم که کار با رشته ها هست ممنون میشم کمکم کنید
<BLOGP>
<div class="post">
<h2><a href="<-PostLink->"><-PostTitle-></a></h2>
<div class="postbody">
<div class="postcontent">
<-PostContent->
<div class="clear"></div>
</div>
<!-- end postcontent -->
<BlogExtendedPost><a href="<-PostLink->">ادامه نوشته</a></BlogExtendedPost>
</div>
<!-- end postbody -->
<div class="postinfo">
<a href="<-PostLink->">+</a> نوشته شده در <-PostDate-> ساعت <-PostTime-> توسط <-PostAuthor->
<BlogComment>&nbsp;|&nbsp;<span dir="rtl" id="comment_<-PostId->"></span></BlogComment>
<div class="clear"></div>
</div>
</div>
<!-- end post -->
<BlogNextAndPreviousBlock>
<div class="nextandprevious">
<BlogPreviousPageBlock>
<a href="<-BlogPreviousPageLink->" class="previouslink" >مطالب جدیدتر</a>
</BlogPreviousPageBlock>
<BlogNextPageBlock>
<a href="<-BlogNextPageLink->" class="nextlink" >مطالب قدیمی‌تر</a>
</BlogNextPageBlock>
<div class="clear"></div>
</div>
</BlogNextAndPreviousBlock>
<NoPost><h1>هیچ پستی وجود ندارد</h1></NoPost>
</BLOGP>
میخوام تو این رشته بگردم اگر این بلوک کد زیر وجود داشت
<NoPost><h1>هیچ پستی وجود ندارد</h1></NoPost>
کل رشته ی بالا با متن داخل بلوک
 <NoPost></NoPost> 
جای گزین بشه یعنی کل متن با این عبارت جایگزین بشه
<h1>هیچ پستی وجود ندارد</h1>
حالا هر رشته ای که داخل این بود با همون دقیقا جایگزین بشه کل رشته ولی اگر همچین بلوک کد
<NoPost></NoPost>
وجود نداشت کل رشته با رشته ی خالی جایگزین بشه که عملا یک رشته ی تهی برگردانده بشه ولی اگه وجود داشت کل رشته با متن داخل بلوک کد ذکر شده جایگزین بشه با تشکر
امیرحسین
۱۹:۱۷ ۱۳۹۷/۰۴/۲۶
من الان این کدا رو نوشتم که به درستی کار میکنه بدون هیچ مشکلی همون نیازهایی که گفتم رو برطرف میکنه ولی استاد این خیلی شلوغ شد و فرمولشم پیچیده شده و خوشم نمیاد اینطوری کد بنویسم اگه ممکنه با یک الگو مشکل من حل شود ممنون میشم
	preg_match('/<BLOGP>.*<NoPost>(.*)<\\/NoPost>.*<\\/BLOGP>/s', $theme, $match);
if(isset($match[1])){
$theme = preg_replace('/<BLOGP>.*<NoPost>(.*)<\\/NoPost>.*<\\/BLOGP>/s', $match[1], $theme);
} else{
$theme = preg_replace('/<BLOGP>.*<\\/BLOGP>/s', '$1', $theme);
}
راه حلتان مشکل خاصی ندارد، این سطح از پیچیدگی در کار با عبارات باقاعده دور از انتظار و غیرطبیعی نیست، اما برای ساختارمند شدن کدنویسی بهتر است مجموعه کدهایی که قرار است عملیات خاصی را انجام دهند به صورت یک تابع بنویسیم و هر زمان به آنها نیاز بود، صرفا تابع را فراخوانی کنیم، مثال:
function matchNoPost($theme){
preg_match('/<BLOGP>.*<NoPost>(.*)<\\/NoPost>.*<\\/BLOGP>/s', $theme, $match);

if(isset($match[1])){
$theme = preg_replace('/<BLOGP>.*<NoPost>(.*)<\\/NoPost>.*<\\/BLOGP>/s', $match[1], $theme);
} else{
$theme = preg_replace('/<BLOGP>.*<\\/BLOGP>/s', '$1', $theme);
}

return $theme;
}

echo matchNoPost($theme_1);
echo matchNoPost($theme_2);
سعید
۱۰:۱۷ ۱۳۹۷/۱۱/۲۴
سلام
در php مثلا برای کنترل شماره پلاک خودرو چه روشی پیشنهاد میکنید لطفا کد رو بنویسد با تشکر
بستگی به ورودی ها و فرمت مد نظر ممکن است الگوی بررسی پلاک متفاوت باشد، یک نمونه:
<?php
function checkIRPlate($str){
$pattern = '/^([0-9]{2})([0-9]{2})([آ-ی]{1})([0-9]{3})$/iu';

if(preg_match($pattern, $str)){
return true;
}

return false;
}
$part_1 = '11';
$part_2 = '22';
$part_3 = 'ب';
$part_4 = '333';
$str = $part_1 . $part_2 . $part_3 . $part_4;

if(checkIRPlate($str)){
echo 'OK';
} else{
echo 'Error';
}
?>
zahra
۱۱:۵۱ ۱۳۹۸/۰۱/۱۶
سلام
من یه متن دارم که که با دستوراتی اعداد داخل متن رو جدا کردم حالا میخام این اعداد رو با هم جمع کنم
باید چکار کنم منو راهنمایی کنید لطفا
مشخص نکرده اید در چه زبانی و خروجی به چه شکلی است؟ با فرض آرایه بودن خروجی در PHP برای جمع مقادیر آرایه یکی از روش های زیر کاربرد دارد:
<?php
$array = array(1, 5, 6, 8, 12);
echo array_sum($array);

function myArraySum($array){
$result = 0;

foreach($array as $key => $value){
$result += $value;
}

return $result;
}
echo myArraySum($array);
?>
ناشناس
۱۰:۱۳ ۱۳۹۸/۱۱/۰۷
سلام
میشه لطفا به سوالم جواب بدید
من می خوام با استفاده از عبارات با قاعده تمام تگ های html رو تشخیص بدم یعنی این <*> خوده این علامت ها <> بعلاوه هرچی که بینشون هست می خوام با یک دستور ریجکسی تمام تگ های اچ تی ام ال رو تشخیص بدم و با یک ریجکس دیگه دستورات شخصی سازی شده بسازم مثلا
P:{} 
می خوام هرجایی از صفحه که این نوشته شد رو تشخیص بدم و محتویات داخل آکولادها رو استخراج کنم یعنی هر رشته ای که توی آکولادها نوشته شده و بعد از انجام یه سری کارها یا پردازش ها روی رشته نتیجه رو جایگزین کنم یا همون replace مثلا
P:{Print->$variable='ahmadi'}
که خروجیش میشه همون ahmadi و جایگزین کلش بشه من فقط می خوام همین
P:{}
رو هرجا که نوشته شده تشخیص بدم از بین اون همه تگ اچ تی ام ال و محتوای نوشته شده توی صفحه و محتویات هر کدوم رو استخراج کنم
میشه لطفا ریجکسشو بهم بدید
کار با عبارات باقاعده پیچیدگی ها خاص خودش را دارد، باید تمام الگوهای متنی ممکن دقیق مشخص باشند تا بتوانیم برای آنها دستور استخراج بنویسیم که فرآیندی زمانبر است، به فرض با توجه به اطلاعات عنوان شده کد زیر برای تشخیص مقدار متغیر کاربرد دارد:
<?php
$html = '<b>P:{Print->$variable=\'ahmadi\'}</b>';
preg_match_all('/(<[^>]*>)([^<]*)(<\/[^>]*>)/i', $html, $matches);
//print_r($matches);
for($i = 0; $i < count($matches[2]); $i++) {
preg_match('/([a-z]+)(\:\{)([a-z]+\->\$[a-z]+[\s]*\=[\s]*\')([a-z]+)(\'\})/i', $matches[2][$i], $match);
//print_r($match);
echo $match[4];
}
?>
توجه کنید که این کد فقط با الگوی فعلی سازگار است و اگر به فرض محل پارامترها تغییر کند قاعدتا عمل نخواهد کرد، همچنین اگر کد HTML مربوط به یک صفحه و آدرس URL است باید ابتدا با توابعی مانند file_get_contents محتوای آنها را در PHP دریافت کنید.
ناشناس
۱۸:۰۳ ۱۳۹۸/۱۱/۰۷
سلام
خیلی ممنون بابت پاسخ سریعتون
خیلی دنبال همین دو خط کد بودم برای یادگیری سریع ریجکس ولی با سرچ پیدا نکردم و توی یک سایت دیگه هم درخواست کردم جواب ندادن بسیار ممنون هدفم این بود یک نمونه حرفه ای ریجکس بنا به تمپلیت انجین لاراول که مدنظرم بود رو داشته باشم که روش تمرکز کنم برای یادگیری که بتونم کارای حرفه ای انجام بدم روی رشته ها چون ریجکس واقعا کارُ راحت می کنه و پردازشُ سبک تر می کنه، بدون ریجکس بخوام انجامش بدم اول اینکه پردازشش سنگین میشه البته نسبت به نوع ریجکسی و دوم کدنویسیش خیلی زیاد و پیچیده میشه
درخواست کدی که برای یک پروژه بتونم ازش استفاده کنم نکردم توضیحات آخر لازم نبود اینا قسمت های حرفه ای هر زبان برنامه نویسی هستند و با اینکه پول دادم 2 پکیج آموزشی پی اچ پی گرونُ خریدم همچین آموزش هایی توشون نبود هر دو هم نوشتن صفر تا صد بعد 1 سال و دیدن کامل آموزش ها هر دوشون اسکلمون کردن واقعا خیلی لطفِ که یکی مثله شما رایگان قرار میده قسمت های حرفه ایُ کاش امثال شما آموزش بسازن که وقتی پول میدیم ارزششو داشته باشه و صفر تا صد دروغی نباشه طرف نوشته صفر تا صد ولی بابت همین file_get_contents پکیج جداگونه گذاشته و بابت همین یک دستور ساده چهلُ یک هزار تومان میگیره پروژرو هم جوری پیش میبرن که خودشون به سختی می فهمن دارن چکار می کنن یک کد میزنن ده تا خطا میده
بله متاسفانه مشکلاتی که اشاره کردید وجود دارد و قابل انکار نیست، به نظر ما تا وقتی تسلط کامل در زمینه ای نداشته باشیم نباید عنوان غیر واقعی مانند سطح حرفه ای یا صفر تا صد روی آموزش ها آن هم غیر رایگان بگذاریم، نکات حرفه ای برنامه نویسی اغلب پراکنده هستند و به مرور زمان با کسب تجربه به دست می آیند، در واقع چیزی به نام صفر تا صد وجود خارجی ندارد، در این حرفه هیچ کس نمی تواند ادعا کند که همه چیز را بلد است!
میثم
۱۹:۰۹ ۱۳۹۹/۰۱/۱۵
سلام
معمولا سه عنصر
$
[
]
برای فیلدهای ورودی خطرناک هستن من قبلا با
$string = str_replace('$','',$string);
اونها رو موقع دریافت حذف می کردم. اما حالا به هر سه موردش برای نمایش متن نیاز دارم.
چطوری این عنصرها رو دریافت کنیم بدون اینکه خطری متوجه سایت بشه؟
یه سوال دیگه خدمت شما داشتم.
من می خوام یه فیلد داشته باشم که در اون نام کاربری چند نفر با علامت @ نوشته بشه نام کاربری فقط شامل اعداد و حروف انگلیسی هست.
مثلا این مقدار قبول باشه.
@ali @reza @d345 @de
اما این مقدار قبول نباشه.
@sd,s @sf5ss% @er4
اینو چطوری با عبارت با قاعده چک کنم؟ اینو نوشتم اما @ و بقیه رو نمیدونم چطوری اضافه کنم
if(preg_match('/^[a-zA-Z0-9]+$/',$username)==1){
ممنونم بابت وقتی که صرف می کنید و پاسخ میدین.
در خصوص سوال اول و ایمن سازی کاراکترهای خاص در PHP بسته به موقعیت در برنامه چند راه وجود دارد:
- اگر یک بک اسلش به ابتدای این کاراکترها اضافه شود اثر خود را به عنوان دستور از دست می دهند، مثال:
$str = str_replace('$', '\$', $str);
- راه حل دیگر استفاده از Single Quotation است که هیچ دستوری در بین علامت های ' ' قابل اجرا نیست:
$str = '$1234'; // => $1234 خروجی
- راه حل بهتر و اصولی تر این است که از ایمن سازی در اکستنشن های MySQLi یا PDO تحت عنوان Prepared Statement و Bind Param استفاده کنید که متن ورودی بدون وجود ریسک امنیتی در دیتابیس ذخیره یا از دیتابیس فراخوانی می شود (در آموزش های مقدماتی MySQL مبحث INSERT در این خصوص توضیح داده ایم).
در مورد سوال دوم کافی است کاراکتر دلخواه را به الگو اضافه کنید (البته برخی موارد دستوری نیاز به درج بک اسلش دارند):
$username = '@sds';
if(preg_match('/^[a-zA-Z0-9@]+$/', $username) == 1) {
echo 1;
} else {
echo 0;
}
میثم
۰۰:۵۲ ۱۳۹۹/۰۱/۱۶
ممنونم خیلی لطف کردین.
اگه از کد زیر استفاده کنم از لحاظ امنیتی مشکلی نداره؟
$string = str_replace('[','&#91;',$string);
$string = str_replace(']','&#93;',$string);
$string = str_replace('$','&#36;',$string);
فقط بدیش اینه که توی تکس فیلدها همون کد html بر میگرده ، راهی هست فرضا با css بشه '&#91 به [ تبدیل کرد؟
به خودی خود از نظر امنیتی مشکلی ندارد اما حفظ امنیت دیتابیس به صورت کلی باید رعایت شود و صرفا به این کاراکترها محدود نیست، یعنی در هر حال باید امنیت ورودی های دیتابیس با توابع و روش های موجود تامین شود، برای نمایش صحیح در فیلدها قبل از چاپ خروجی مقادیر را به حالت اولیه برگردان کنید، می توانید برای این کار تابع بنویسید که کاربرد ساده تری داشته باشد.
KhashayarPrk
۱۳:۱۳ ۱۳۹۹/۰۴/۲۰
<?php
$str = 'HTML (CSS)Java(PHP)';
preg_match('/\((.*)\)/i', $str, $match);
print_r($match);
?>
سلام. میخوام الگو تمام کلمات داخل پرانتز رو بدون پرانتز بریزه ارایه با این کد فقط یک پرانتز رو جواب میده.
برای استخراج تمام موارد داخل پرانتز در آرایه از تابع preg_match_all به صورت زیر استفاده کنید:
<?php
$str = 'HTML (CSS)Java(PHP)';
preg_match_all('/\(([^\)]+)\)/i', $str, $match);
print_r($match[1]);
?>
مینا
۱۹:۲۷ ۱۳۹۹/۰۸/۱۹
سلام. من میخوام از regex توی ماشین حساب استفاده کنم ممنون میشم منو راهنمایی کنین
سوالتان کلی است، لطفا مشکل را به صورت موردی و با جزئیات مطرح کنید تا امکان راهنمایی وجود داشته باشد، در کدام بخش کدها و به چه شکلی می خواهید از Regex استفاده کنید؟
علی
۰۴:۵۶ ۱۳۹۹/۱۱/۰۵
با سلام تشکر از سایت خوبتون و اموزشای خوبی که قرار میدین
یک سوال داشتم من میخوام از یک فایل رشته ای همانند :
$a = '
test1
min
2min
https://webgoo.ir
15min 5s
'
;
با عبارات با قاعده اون 2min و 15min 5s رو به ترتیب استخراج کنم ازش.
preg_match_all('#(.*?)min#',$a,$b);
از چنین الگویی استفاده کردم ولی دقیق نیست چون min خالی اول و 2min رو برمیگردونه برام اما من 2min و 15min 5s رو در اینجا لازم دارم تا به ترتیب دریافت کنم (ممکن است تعداد کم یا زیاد و حتی همه min و یا همراه s باشند)
ایا چنین الگویی میشه نوشت؟
لطفا راهنمایی کنید
پیشاپیش سپاس
ابتدا باید مشخص کنید چه الگوهایی مد نظر است، به فرض شروع خط با عدد (چه تعداد) باشد؟ سپس عبارت min بیاید؟ در ادامه فاصله (یک یا بیشتر) اختیاری است؟ در ادامه عدد (چه تعداد) باید باشد؟ s آخر اختیاری است؟ با توجه به توضیحات می توانید دستور را به شکل زیر تغییر دهید اما تا زمانی که مشخص نکرده اید نتیجه مد نظر دقیقا از چه الگو یا الگوهایی پیروی می کند نمی توان دستور کاملی نوشت:
<?php
$var = preg_match_all('/([0-9]+min\s*[0-9]*[a-z]*)[\r\n]/ims', $a, $b);
print_r($b);
?>
علی
۲۱:۱۲ ۱۳۹۹/۱۱/۰۵
سلام تشکر میکنم از شما و سایت فوق العاده عالی تون
مشکلم حل شد تشکر میکنم موفق باشید
خواهش، فقط دقت کنید کد ارائه شده بر اساس رشته متنی فعلی است که درج کرده اید، اگر رشته با الگوی جدیدی تغییر کند ممکن است کد نیاز به اصلاح داشته باشد (تمام الگوهای مد نظر باید مشخص باشند تا کد کامل شود).
حسینی
۱۴:۱۰ ۱۴۰۰/۰۲/۱۷
سلام.
یه سوال خدمت شما داشتم.
فرض کنیم str زیر رو داریم.
علی ali 110 رضا hadi محمد 545 mahdi 
چطور می تونیم :
1- فقط اعداد رو از str بیرون بکشیم. یعنی خروجی بشه 110545
2- فقط عبارت فارسی رو بیرون بکشیم. یعنی خروجی بشه : علی رضا محمد
3- فقط حروف انگلیسی بیرون بکشیم. یعنی خروجی بشه : ali hadi mahdi
4- فقط اعداد و عبارت فارسی بیرون بکشیم. یعنی خروجی بشه : علی 110 رضا محمد 545
5- فقط اعداد و عبارت انگلیسی بیرون بکشیم. یعنی خروجی بشه : ali 110 hadi mahdi 545
ممنونم. ببخشید سوالات زیاد شد.
با نمونه کد زیر در PHP می توانید موارد مد نظر را از رشته استخراج کنید:
<?php
$str = 'علی ali 110 رضا hadi محمد 545 mahdi';
preg_match_all('/([0-9]+)/iu', $str, $matches);
foreach($matches[0] as $key => $value){
echo $value;
}
preg_match_all('/([آ-ی]+)/iu', $str, $matches);
foreach($matches[0] as $key => $value){
echo $value . ' ';
}
preg_match_all('/([a-z]+)/iu', $str, $matches);
foreach($matches[0] as $key => $value){
echo $value . ' ';
}
preg_match_all('/([آ-ی0-9]+)/iu', $str, $matches);
foreach($matches[0] as $key => $value){
echo $value . ' ';
}
preg_match_all('/([a-z0-9]+)/iu', $str, $matches);
foreach($matches[0] as $key => $value){
echo $value . ' ';
}
?>
اگر زبان جاوا اسکریپت مد نظر است بفرمائید تا به پاسخ اضافه شود.
more لطفا پیش از ارسال دیدگاه نکات زیر را مد نظر داشته باشید:
- به سوالات کلی، زمانبر، مبهم و مشکلاتی که تلاشی برای رفع آنها نکرده باشید پاسخ مختصر داده شده یا به بخش برنامه نویسی اختصاصی ارجاع داده می شوند.
- کدها و اسکریپت های طولانی را ترجیحا در یک صفحه وب آنلاین یا به صورت حساب موقت و آزمایشی قرار دهید تا امکان بررسی دقیق مشکل و خطایابی میسر باشد.
- تمام دیدگاه های ارسالی خوانده شده و برای هر کاربر مدت زمان لازم جهت پاسخگویی در نظر گرفته می شود، لطفا از طرح سوالات متعدد در بازه زمانی کوتاه خودداری کنید.



 refresh
10 × 10
3 × 8
20 × 20
=
آخرین دیدگاه ها
more برای دسترسی سریع به یادداشت مربوطه می توانید از لینک مطلب در کادر زیر استفاده کنید.
سیدعباسی
با تشکر از شما خیلی ممنون مشکلم درست شد فقط یه مشکل دارم چطوری می تونم با php متنی که می نویسم یه قسمت...
۱۴۰۳/۰۴/۲۶

پرتو
سلام ببخشید مزاحم میشم جواب سوال من کو؟
۱۴۰۳/۰۴/۲۵

سیدعباسی
ببخشید برای سوال و کد قبلی که براتون نوشتم میخوام با کد قبلی یک لینک رو بررسی کنم بعد عکسهای اون مطلب رو پیدا کنم...
۱۴۰۳/۰۴/۲۵

سیدعباسی
با تشکر از شما متوجه شدم با این کد چطوری میتونم عکس یک مطلب رو دربیارم و لینکش رو جدا کنم؟ روی کد...
۱۴۰۳/۰۴/۲۵

سیدعباسی
سلام من دو روز پیش یه کد براتون فرستادم واسه ارسال متن به تلگرام اونو درست کردم فقط این کد ازش می خوام...
۱۴۰۳/۰۴/۲۴

سیدعباسی
با سلام من مطالب سایتم رو با این تابع به تلگرام ارسال می کنم فقط مشکلی که باهاش دارم اینکه هیچ تگی رو قبول...
۱۴۰۳/۰۴/۲۲

سارا اکبری
لطفا کد کپچا رو درست کنید هر چی کپچا رو میزنیم میگه اشتباهه حتما باید کپچا رو دستی خودمون رو دکمش بزنیم رفرش بشه بعد...
۱۴۰۳/۰۴/۲۱

سارا اکبری
سلام استاد عزیز وقت بخیر بنده ی تعداد افراد انلاین ساده نوشتم ببینید برای پروژه های بزرگ اوکیه و مشکلی پیش نمیاد ؟...
۱۴۰۳/۰۴/۲۱

پرتو
سلام خوبید؟ خسته نباشید ببخشید مزاحم میشم ممنون از جوابتون راستش بعضی وقتا از بس سوالاتم زیاده روم نمیشه ازتون بپرسم مثل امشب که چیکار...
۱۴۰۳/۰۳/۱۳

پرتو
سلام خوبین؟ خسته نباشید یه سوال من منوی سمت راست قالبم نوشته هاش چسبیده به بردر باید چیکار کنم که درست شه؟ یعنی منظورم اینکه...
۱۴۰۳/۰۳/۰۹

پرتو
سلام خوبید؟ بلاکفا باز دچار مشکل شده یا فقط برای من دچار مشکل شده؟ منظورم اینکه خیلی دیر باز میشه و فقط برای فایرفاکس هم...
۱۴۰۳/۰۳/۰۱
  در انتظار بررسی: ۲
 پاسخگویی به سوالات ممکن است تا ۲۴ ساعت زمان ببرد.