عبارات با قاعده کاربرد بسیاری در کار با رشته ها در زبانهای برنامه نویسی و پایگاه داده دارند. در این پست به بررسی عبارات باقاعده یا همون regular expressions خارجیا میپردازیم.
اول اینکه از عبارات با قاعده برای چک کردن اینکه یک رشته از یک الگو و قاعده پیروی میکند یا خیر، استفاده میشود. و مسئله دوم این است که سینتکس عبارات باقاعده در اکثر زبانها مشترک است. ما در این پست به بررسی عبارات باقاعده با سینتکس جاوااسکریپت و php میپردازیم.
در زبانهای برنامه نویسی جاوااسکریپت و php ما نیاز داریم که عبارات با قاعده خود را بین کاراکتری مثل / قرار دهیم. در مثال زیر نیازی به پوشش عبارت باقاعده بین ' و " نیست. مثلا :
var regex = /a/
عبارت با قاعده بالا تمام رشته هایی که حرف a درون آنهاست را میپذیرد. برای درک بهتر به مثال زیر دقت کنید :
var regex = /a/ const term = 'abbas bagheri'; var output = regex.exec(term); console.log(output); // output : true regex = /a/ const term2 = 'sourosh'; output = regex.exec(term); console.log(output); // output : false
در مثال اول چون در رشته حرف a داشتیم جواب true شد و در رشته دوم چون a نداشتیم جواب آزمایش منفی بود. بهمین سادگی یک قاعده ساده نوشتیم و قاعده ما این بود که رشته باید درونش کاراکتر a باشد.
برای مثال در ورودی از کاربر یک رشته میگیریم و میخواهیم چک کنیم که آیا در این رشته ورودی عبارت 'ab' وجود دارد یا خیر؟
<?php $regex = '/ab/'; $input = 'abbas'; $output = preg_match($regex,$input); echo $output; // output : 1 (true) $regex = '/ab/'; $input = 'bagheri'; $output = preg_match($regex,$input); echo $output; // output : 0 (false)
در مثال اول چون در رشته abbas رشته ab وجود داشت جواب درست بود و در رشته bagheri جواب منفی شد. یک قاعده ساده ایجاد کردیم و این قاعده چک میکند که درون رشته ای که از کاربر می آید رشته ab وجود دارد یا نه؟
به مثال زیر دقت کنید :
<?php $regex = '/ab/'; $input = 'Abbas'; $output = preg_match($regex,$input); echo $output; // output : 0 (false)
مثلا کاربر بجای abbas رشته Abbas را وارد کند. تفاوت این دو فقط درون کوچک و بزرگ بودن حروف است. جواب کد منفی میشود زیرا درون رشته Abbas رشته ab وجود ندارد. در واقع عبارات باقاعده به طور پیش فرض به حروف کوچک و بزرگ حساس هستند. ما میتوانیم این حساسیت را با modifier i تغییر دهیم. گفتیم قاعده خود را بین دو علامت / قرار میدهیم. برای تغییر modifier حساسیت به حروف بزرگ و کوچک بعد از / پایان قاعده یک کاراکتر i قرار میدهیم.
<?php $regex = '/ab/i'; $input = 'Abbas'; $output = preg_match($regex,$input); echo $output; // output : 1 (true)
در مثال بالا قاعده خود را طوری نوشتیم که به حروف کوچک و بزرگ حساس نباشد. گاها پیش می آید که نیاز داریم قاعده ای بنویسیم که به حروف بزرگ و کوچک حساس نباشد از modifier i استفاده میکنیم. در ادامه ممکن است به modifier تغییر حالت یا اصلاح هم بگوییم.
مثلا ما یک رشته از کاربر میگیریم. میخواهیم بررسی کنیم که این رشته دریافتی با ab شروع میشود یا خیر؟ برای این مورد باید با کاربر کاراکتر ^ در عبارات با قاعده آشنا شویم.
var regex = /^ab/i
در این مثال وقتی عبارت با قاعده ما با ^ شروع میشود به معنای این است که ab حتما باید در ابتدای رشته ورودی قرار بگیرید. به مثال زیر توجه کنید:
var regex = /^ab/i var output = regex.exec('Abbas Bagheri'); console.log(output); // output : 1 or true regex = /^ab/i output = regex.exec(" Abbas Bagheri"); console.log(output); // output : 0 or false
تفاوت این دو مثال این است که در مثال اول رشته ما با ab شروع میشود ولی در مثال دوم رشته ما با کاراکتر فضای خالی شروع میشود. دقت کنید که عبارات باقاعده به فضای خالی یا اسپیس هم حساس هستند.
پس اگر کاراکتر ^ در ابتدای عبارت باقاعده بیاید به معنای این است که رشته ورودی باید با این کاراکتر یا این رشته یا به عبارتی این قاعده شروع شود.
مسئله: از کاربر یک رشته میگیریم، میخواهیم بررسی کنیم این رشته با کاراکتر i پایان میابد یا خیر؟
برای این مورد باید با کاربرد کاراکتر $ در پایان عبارات باقاعده آشنا شویم. وقتی در انتهای عبارات با قاعده خود کاراکتر دلار $ قرار میدهیم دو اتفاق رخ میدهد. اول اینکه قاعده ما روز به روز گرونتر میشود و دوم به این معناست فقط رشته هایی را میپذیرد که با این قاعده پایان میابند. به مثال زیر توجه کنید :
var regex = /i$/i var output = regex.exec('Abbas Bagheri'); console.log(output); // output : 1 or true regex = /i$/i output = regex.exec("Abbas Baghery"); console.log(output); // output : 0 or false
در مثال اول رشته ما با i خاتمه میافت پس جواب مثبت بود و رشته مثال دوم با y، پس جواب منفی شد. پس به کاربرد کاراکترهای ^ در ابتدای رشته و $ در انتهای رشته حتما باید آشنا شده باشید.
اگر در ابتدای قاعده (بعد از / شروع) کاراکتر ^ بگذاریم به معنای این است که حتما رشته ما با این قاعده شروع شود مثلا حرف اولش a باشد و $ در پایان قاعده (قبل از / بسته) به معنای این است که رشته ورودی باید با این قاعده پایان یاید.
مسئله : یک قاعده ایجاد کنید که رشته سه حرفی را بپذیرد که با a شروع میشوند و با e هم خاتمه میابند.
به قاعده زیر دقت کنید.
regex = /^a/
میدانیم این قاعده به این معناست که رشته ما باید با کاراکتر a (نه A) شروع شود.
regex = /e$/
معنای این قاعده هم این است که رشته ما با کاراکتر e پایان یابد.
به قاعده زیر دقت کنید :
regex = /^ٌae$/
دقت کنید برای حل این مسئله نمیتوانیم از قاعده بالا استفاده کنیم چون این قاعده رشته هایی میپذیرد که با ae شروع شده و با همان ae پایان میابد. یعنی اگر کاربر دقیقا در ورودی ae وارد کرد (حتی بدون فاصله) جواب مثبت میشود و به ازای تمام رشته های دیگر مانند aejkjijcae جواب منفی است.
برای حل مسئله بالا باید با کاربرد کاراکتر . (غریبه نیست، همان نقطه خودمان میشود) در عبارات باقاعده آشنا شویم. این کاراکتر به این معناست که بجایش هر کاراکتری میتواند قرار بگیرد. وقتی میگوییم هر کاراکتری منظومان دقیقا همه کاراکترهای موجود در کامپیوتره. مانند خود . یا ! یا حروف یا اعداد!!
به قاعده زیر دقت کنید:
regex = /a.e/
این قاعده رشته هایی را میپذیرد که درونشان یک رشته سه حرفی باشد، طوری که آن رشته سه حرفی با a شروع شده و با e پایان یابد و نقطه وسط هم منظورش اینه که بجایش هر چیزی باشد مانند : ate ، a8e یا a#e
مثلا قاعده بالا رشته های ateful و pater را میپذیرد. دقت کنید بجای کاراکتر نقطه فقط یک کاراکتر میتواند باشد. مثلا agger قبول نیست. چون بین a و e دو کاراکتر داریم.
ما گفتیم رشته ما سه حرف دارد که با a شروع شده و با e هم پایان یابد. ولی در قاعده بالا این مورد را در نظر نگرفتیم. ما کاربرد کاراکترهای ^ و $ را میدانیم. پس قاعده خود را به این صورت تغییر میدهیم :
regex = /^a.e$/
خب جواب مسئله ما این قاعده است. ^ به این معناست که رشته ورودی باید با a شروع شده و کاراکتر $ به این معناست که رشته ورودی باید با e پایان یابد. کاراکتر نقطه هم به این معناست که بین a و e یک کاراکتر باید باشد.
از علامت سوال یا ? برای اختیاری کردن وجود یک کاراکتر در رشته استفاده میکنیم. مثلا در مثال بالا اگر مسئله را به صورت زیر تغییر دهیم :
مسئله : یک عبارت باقاعده طراحی کنید که رشته هایی را بپذیرد یک با a شروع شده و با e پایان یابد. بین a و e یک کاراکتر میتواند قرار بگیرد.
به قاعده زیر دقت کنید :
regex = /^a.e$/
این قاعده به این معناست که حتما باید بین a و e یک کاراکتر (نه بیشتر از یکی) وجود داشته باشد. ولی برای مسئله ما این مورد خوب نیست چون اگر کاربر در ورودی ae را وارد کرد جواب منفی میشود. برای حل این موضوع باید بگوییم که کاراکتر بین a و e میتواند وجود نداشته باشد یا به عبارتی وجودش اختیاری است. اینجا از ؟ کمک میگیریم. قاعده خودر را بصورت زیر تغییر میدهیم:
regex = /^a.?e$/
با علامت سوال مشخص کردیم که وجود کاراکتر بین a و e اختیاری است.
به قاعده زیر دقت کنید:
regex = /^a.e?$/
در این قاعده وجود کاراکتر e در پایان رشته اختیاری شده یعنی تنها رشته هایی را میپذیرد که با a شروع شده و بعد از a یک کاراکتر دیگر هم باید وجود داشته باشد و در کاراکتر سوم یا باید e باشد یا چیزی نباشد مثلا age و ag را تایید میکند. چون مشخص کردیم e اختیاری است ولی agx را نمیپذیرد.
مسئله : یک قاعده طراحی کنید بطوری که رشته های سه حرفی را بپذیرد که با a شروع شده و با i هم خاتمه میابند. مثلا ai قبول نیست ولی aeri و a9993n#dsei قبول است.
به قاعده زیر دقت کنید :
regex = /^a.i$/
این قاعده تنها برای کلمات سه حرفی جواب میداد. اما ما نیاز داریم که بین a و i بین یک تا بینهایت کاراکتر داشته باشیم. برای هندل کردن این موضوع از کاراکتر + کمک میگیریم.
به قاعده زیر دقت کنید.
regex = /^a+i$/
دقت کنید به کمک کاراکتر + در عبارت باقاعده مشخص میکنیم کاراکتر قبل از خودش حداقل یک بار تا بی نهایت بار میتواند تکرار شود. یعنی در این قاعده میتوانیم بینهایت a را تکرار کنیم یعنی کلمات i و aaaai و aaaaabi را میپذیرد ولی i را بدلیل عدم وجود a یا aiii را بدلیل اینکه i چند بار تکرار شده را نمیپذیرد.
به قاعده زیر دقت کنید:
regex = /^ai+$/
در این قاعده بر عکس مثال بالاتر مشخص شده رشته با یک a شروع شده و با بین 1 تا بینهایت i پایان یابد مثلا ai و aiiiiiiiiiiiiiiiiiiiiiiiiiiiiii .
به این قاعده دقت کنید :
regex = /^a.i$/
به این قاعده دقت کنید بین a و i یک کاراکتر باید باشد. اما ما میخواهیم بین a و i حداقل یک کاراکتر تا بینهایت وجود داشته باشد. برای این مورد از کاراکتر + کمک میگیریم.
regex = /^a.+i$/
قاعده بالا جواب مسئله است. رشته ورودی را میپذیرد که با a شروع شده، با i تمام شده و بین این دو حداقل یک کاراکتر میتوان وجود داشته باشد.
تفاوت کاراکتر * با + فقط در تعداد تکرار است. به مسئله زیر دقت کنید:
مسئله : یک قاعده طراحی کنید بطوری که رشته هایی را بپذیرد که با a شروع شده و با i هم خاتمه میابند. مثلا ai ، aei و a#456i قبول است.
به قاعده زیر دقت کنید :
regex = /^a.+i$/
این قاعده تمام رشته های سه حرفی برای مسئله بالا را پوششن میدهد. اما ai را پوشش نمیدهد، زیرا بین a و e هیچ کاراکتری نداریم. گفتیم + بعد از یک کاراکتر به این معناست که حداقل آن کاراکتر یک بار تکرار در رشته ورودی شود. ولی ما نیاز داریم که ai را هم بپذیرد. فقط کافیست + را به * تغییر دهیم:
regex = /^a.*i$/
این قاعده جواب مسئله ماست. به قطعه کد زیر دقت کنید.
const words = [ 'abas baghei' , 'Abas Bagheri' , 'Abbbi', 'ai', 'ci' ]; for (var i=0;i<5,i++){ var regexWithPlus = /^a.+i$/i var regexWithStar = /^a.*i$/ console.log(' plus :', regexWithPlus.exec(words[i]) ); console.log( 'star :', regexWithStart.exec(words[i]) ); } // output i=0 ; plus : true , star : true // output i=1 ; plus : true , star : false // output i=2 ; plus : true , star : false // output i=3 ; plus : false , star : true // output i=4 ; plus : false, star : false
در مثال بالا برای abas bagheri جواب هردو مثبت شد، زیرا بین a و i چند کاراکتر وجود دارد.
در مثال دوم برای Abas Bagheri حالت با علامت جمع به دلیل modifier i مثبت شد ولی حالت با علامت ستاره منفی شد.
در مثال سوم هم به دلیل مثال قبلی همین اتفاق رخ داد.
در مثال چهارم برای کلمه ai در حالت با علامت جمع منفی شد زیرا حداقل یک کاراکتر بین a و i وجود ندارد ولی در قاعده با علامت * مثبت شد زیرا کاراکتر قبل از علامت ستاره میتواند صفر بار تکرار شود یا به معنای دیگر میتواند وجود نداشته باشد. میشه به شکلی غیر رسمی گفت * ترکیت + و ? است.
در مثال ci هم چون رشته با a شروع نشده بود در هردو حالت منفی شد.
مسئله : یک برنامه طراحی کنید که رشته ورودی را بررسی کند و فقط آنهایی که با ab شروع شده و یا با e تمام شده را بپذیرد.
طبق این مسئله رشته ما باید با ab شروع شده باشد مثلا abbas یا خود ab و یا باید با e تمام شده باشد مثلا age. لزومی ندارد که هردو شرط برقرار باشند.
به قواعد زیر دقت کنید :
startWithABRegex = /^ab/ // ex: ab ,abbas , abadis , ... endWithERegrx = /e$/ // ex: age , e , ajdjjde ,...
قاعده اول میشود شرط اول و قاعده دوم میشود شرط دوم و به همین راحتی از آن استفاده میکند.
var startWithABRegex = /^ab/ // ex: ab ,abbas , abadis , ... var endWithERegrx = /e$/ // ex: age , e , ajdjjde ,... var input = 'age' console.log( (startWithABRegex.exec(input) || startWithABRegex.exec(input)) ); // output : true startWithABRegex = /^ab/ // ex: ab ,abbas , abadis , ... endWithERegrx = /e$/ // ex: age , e , ajdjjde ,... input = 'abbas' console.log( (startWithABRegex.exec(input) || startWithABRegex.exec(input)) ); // output : true startWithABRegex = /^ab/ // ex: ab ,abbas , abadis , ... endWithERegrx = /e$/ // ex: age , e , ajdjjde ,... input = 'bagheri' console.log( (startWithABRegex.exec(input) || startWithABRegex.exec(input)) ); // output : false
در مثال اول age با e پایان یافت پس نتیجه true میشود. در مثال دوم abbas با ab شروع شده پس دوباره شرط برقرار است و true میشود ولی در مثال سوم هیچ کدام از دوحالت برقرار نیست. پس نتیجه false میدهد و رشته را نمیپذیرد.
ما آمدیم و دو قاعده مجزا تعریف کردیم و با or جاوااسکریپت رشته ورودی را برای دو قاعده چک کردیم. تا یکی از دوقاعده لااقل true شود. اما در مسئله باید یک قاعده طراحی کنیم نه دوتا یا سه تا یا بیشتر .... :)
برای حل این موضوع دو قاعده را در یک قاعده کنار هم مینویسیم و بین آن دو علامت | قرار میدهیم :
var regex = /^ab|e$/ // ex: ab ,abbas , abadis , age , e , ajdjjde ,... var input = 'age' console.log( regex.exec(input) ); // output : true var regex = /^ab|e$/ // ex: ab ,abbas , abadis , age , e , ajdjjde ,... input = 'abbas' console.log( regex.exec(input) ); // output : true var regex = /^ab|e$/ // ex: ab ,abbas , abadis , age , e , ajdjjde ,... input = 'bagheri'; console.log( regex.exec(input) ); // output : false
این قاعده رشته هایی را میپذیرد یکی از دو قاعده در طرفین کاراکتر | را داشته باشد یا با ab شروع شود یا با e پایان یابد. دقت کنید برای | یا or فقط یکی از شرطها درست باشد کافیست.
به مثالهای زیر دقت کنید :
regex = /^a|i$|ab|^s.*y$/
این قاعده از ترکیب 4 قاعده دیگر بوجود آمده. رشته ورودی اگر یکی از شرایط را داشت، قاعده ما آنرا میپذیرد.
حالت اول /a^/ : تمام رشته هایی که با کاراکتر a شروع شده باشند.
حالت دوم /$i/ : تمام رشته هایی که با کاراکتر i تمام شده باشند.
حالت سوم /ab/ : تمام رشته هایی که شامل ab شوند. لزومی ندارد ab در ابتدا بیاید یا در انتهای رشته.
حالت چهارم /$y*.s^/ : تمام رشته هایی که با y شروع شده و با s تمام شوند مانند yes و ys و yaaaas!
regex = /cc|er/
این قاعده هم رشته هایی را میپذیرد که درون خود cc یا er را داشته باشند.
دقت کنید در جاوااسکریپت و php علامت | دو کاراکتر را از هم جدا نمیکند مثلا در مثال بالا منظور c یا e نیست. بلکه دو قاعده قبل و بعد خودش را کامل از هم جدا میکند و دو قاعده مجزا در نظر میگیرد.
مسئله : یک عبارت منظم ( باقاعده) طراحی کنید که فقط رشته هایی بپذیرد که در آن چند بار ab تکرار شده باشد. مانند ab و abababab قبول است ولی abaab قبول نیست.
به عبارت باقاعده زیر دقت کنید :
regex = /ab/
در این قاعده ما مشخص کردیم درون رشته ما ab وجود داشته باشد. مثلا abas هم قبول میکند. برای مسئله ما خوب نیست.
regex = /^ab$/
گفتیم این قاعده هم ab را فقط میپذیرد.
regex = /^ab.*ab$/
این قاعده هم مشخص میکند که رشته ها با ab شروع شده و با ab هم پایان یابند . مثلا abejenjeab را میپذیرد. و حتی ab را نمیپذیرد.
ما باید با کاربرد پرانتز درون عبارات منظم آشنا شویم. در حقیقت وقتی درون یک پرانتز باز و بسته، یک رشته یا عبارت منظم قرار دهیم میتوان با عبارت داخل پرانتز مانند یک کاراکتر رفتار کرد(البته این یک بیان برای درک بهتر پرانتزها بود. ). یا به عبارتی کاراکترهای درون پرانتز را باهم گروه کرد. بهرحال به مثال های زیر دقت کنید.
regex = /^.(ab)?$/ // examples: c , cab , i , iab
این مثال رشته هایی را می پذیرد که با یک کاراکتر دلخواه شروع شده و بعد از این یک کاراکتر میتوانیم ab داشته باشیم یا نه. مثلا رشته های c و cab هردو را میپذیرد.
regex = /^u(ab)*$/ // examples: u , uab , uabab , uababab, ...
این الگو مشخص میکند رشته با u شروع شده و بعد از آن بین 0 تا بینهایت بار ab تکرار شود.
regex = /^u(ab)+$/ // examples: uab , uabab , uababab, ...
این الگو مشخص میکند رشته با u شروع شده و بعد از آن بین 0 تا بینهایت بار ab تکرار شود. تنها تفاوت با مثال بالاتر در این است که u را نمیپذیرد زیرا باید ab حداقل یکبار تکرار شود. به مثال زیر اکنون دقت کنید.
regex = /^uab+$/ // examples: uab, uabb, uabbb, uabbbbb, ...
اگر پرانتز را دور ab قرار نداده بودیم علامت جمع فقط برای کاراکتر قبل از خودش یعنی کاراکتر b عمل میکرد. اما با پرانتز دور ab مشخص کردیم به ab نگاه کند. یا به عبارت دیگر ab مانند یک کاراکتر عمل کند نه دو کاراکتر مجزا!
خب برمیگردیم به مسئله خودمان. رشته باید با ab شروع شده و پایان یابد و ab هم بین 1 تا بینهایت بار تکرار شود. گفتیم برای حداقل یکبار تکرار علامت جمع و اینکه علامت جمع به ab نگاه کند میگذاریمشان درون پرانتز.
regex = /^(ab)+$/ // ex : ab,abab , ababab , abababababababab , ...
خب جواب مسئله ما این است. متاسفانه یا خوشبختانه کاربرد علامت پرانتز فقط این نیست. مسئله بالا را کمی تغییر میدهیم.
مسئله : یک عبارت منظم ( باقاعده) طراحی کنید که فقط رشته هایی بپذیرد که در آن چند بار ab و ai تکرار شده باشد یا با ac شروع شده باشند. مثلا aceecec و aiaiaiai هم مورد قبول است. خب ما میتوانیم سه تا قاعده مجزا طراحی کنیم :
regexAC = /^ac/ //ex: aceijeiej, ac , acsksks regexAB = /^(ab)+$/ //ex: ab , abab, abababab , ... regexAI = /^(ai)+$/ //ex: ai, aiai , aiaiaiaiai
میدونیم که با کاراکتر | میتوان سه قاعده را کنار هم گذاشت و مسئله را حل کرد.
regex = /^ac|^(ab)+$|^(ai)+$/ //ex: aceijeiej, ac , acsksks ,ab , abab, abababab , ai, aiai , aiaiaiaiai , ...
جواب درست است اما با پرانتز هم میتوان کمی قاعده را کوتاه تر و جمع و جورتر کرد.
regex = /^ac|^(ab|ai)+$/ //ex: aceijeiej, ac , acsksks ,ab , abab, abababab , ai, aiai , aiaiaiaiai , ...
برای درک بهتر این موضوع به قاعده زیر دقت کنید.
regex = /^(ab|ai)+$/ //ex: ab , abab, abababab , ai, aiai , aiaiaiaiai , ...
در بخش قبل گفتیم که علامت | دو بخش قاعده را از هم جدا میکند. و دو قاعده مجزا در نظر میگیرد، اما وقتی از علامت | درون پرانتز استفاده کنیم فقط به درون پزانتز نگاه میکند و کاری به بیرون پرانتز ندارد.
مسئله : قاعده ای طراحی کنید که رشته ای را بپذیرد که با ab یا aca شروع شده و با i هم خاتمه یابد.
مثلا abbas bagheri و acarri مورد قبول هستند ولی adri مورد قبول نیست.
دو قاعده داریم یا با ab شروع شده یا با aca :
regex = /^ab.*i$|^aca.*i$/
به کمک پرانتز میتوان خلاصه تر نوشت :
regex = /^(ab|aca).*i$/
در این قاعده رشته باید با ab یا aca شروع شده و بعد از آن هرچیزی میتواند باشد ولی این رشته باید با i خاتمه یابد. اما برای ab و aca حرف a در ابتدا مشترک است. پس :
regex = /^a(b|ca).*i$/
در این قاعده حرف ابتدایی رشته باید a باشد، بعد از a یکی از رشته های درون پرانتز بیاید و بعد از آن هر کاراکتری و در نهایت رشته با i تمام شود.
به مثال زیر توجه کنید :
regex = /^a(bu|ci|th)+z$/
این قاعده رشته هایی میپذیرد که a در ابتدا و z در انتهای آن باشد. و بین این دو فقط تکرار با یکی از موارد داخل پرانتز (منظور این نیست که مثلا فقط bu تکرار شده باشد.) مجاز است. مثلا abubucicicibuthz مجاز است.
مسئله : یک قاعده طراحی کنید که رشته 9 حرفی را بپذیرد.
همه کاراکترها مجاز هستند پس باید از نقطه استفاده کنیم. قاعده ما با نقطه شروع شده با نقطه پایان میابند و یک نقطه هم باید بینشان باشه.
regex = /^...$/
این قاعده مسئله را حل میکند. کاراکتر شروع هر چیزی میتواند باشد. کاراکتر انتها و میانی هم همینطور. اما اگر مسئله بجای سه حرفی گفت 1000 حرفی چطور؟
با استفاده از کروشه تعداد تکرار هر کاراکتر را تعیین میکنیم.
regex = /^.*$/
وقتی بعد از یک کاراکتر ستاره بگذاریم به معنی این است که این کاراکتر بین صفر تا بینهایت بار میتواند تکرار داشته باشد.
regex = /^.+$/
وقتی بعد از یک کاراکتر علامت جمع بگذاریم به معنی این است که این کاراکتر بین یک تا بینهایت بار میتواند تکرار داشته باشد.
regex = /^.{1000}$/
علامت کروشه به معنای آن است که کاراکتر قبل از آن دقیقا باید به تعداد عدد داخل کروشه تکرار شود. مثلا اینجا فقط رشته های 1000 کاراکتره را میپذیرد. پس راه حل منطقی تر مسئله بالا استفاده از {} است.
regex = /^.{3}$/
به مثال زیر دقت کنید :
regex = /^ab{2}/
این قاعده فقط رشته هایی را میپذیرید که در ابتدای آن abb وجود داشته باشد.
regex = /^(ab){2}/
این قاعده رشته هایی را میپذیرد که در ابتدای آن abab امده باشد.
regex = /^(ab|cd){2}/
این قاعده رشته ای را میپذیرد که در ابتدای آن یکی از ترکیبات ab با cd آمده باشد مثلا cdab ابتدای رشته باشد. دقت کنید abab و cdcd هم مجاز است.
مسئله : قاعده ای طراحی کنید که رشته هایی را بپذیرد که درون آن ab سه تا پنج بار پشت سر هم تکرار شده باشد. مثلا ascasabababllk
regex = /(ab){3,5}/
اگر در کروشه بجای یک عدد دو عدد قرار دهیم به معنای محدودیت تعداد تکرار است. دقت کنید منظور اینجا بین 3 تا 5 است یعنی 3 4 و 5 نه فقط 3 و 5.
مسئله : یک قاعده طراحی کنید که فقط رشته های عددی که بین 5 تا 15 رقم دارند را بپذیرد.
ما میتوانیم تعداد تکرار کاراکتر را محدود کنیم.
regex = /.{5,15}/
این قاعده تمام رشته هایی که بین 5 تا 15 کاراکتر هستند را میپذیرد. گفتیم علامت نقطه یعنی همه کاراکترها!
برای اینکه بتوانیم نوع کاراکتر را محدود کنیم بجای (نه بعد از) علامت نقطه از براکت استفاده میکنیم :
regex = /[0123456789]{5,15}/
به قاعده بالا دقت کنید. اول اینکه براکت با پرانتز کاملا معنای متفاوتی دارد. دوم اینکه وقتی کاراکتری را درون براکت میگذاریم یعنی آن کاراکتر مجاز است بجای براکت بنشیند. مثلا یکی از ارقامی که گذاشتیم. بجای رقم میتوان حروف لاتین یا عربی گذاشت. یا هر کاراکتری که وجود دارد.
regex = /^[2ی54v re]+$/
مثلا این برنامه فقط رشته هایی را میپذیرد که فقط شامل کاراکترهای مجود درون براکت باشند. مثلا 23rv.
دقت کنید اسپس که درون براکت گذاشتیم این معنا را میدهد که اسپیس هم کاراکتر مجاز است.
برمیگردیم سر مسئله :
regex = /[0123456789]{5,15}/
گفتیم این قاعده رشته هایی که شامل رشته ای دیگر که متشکل از ارقام عددی است را میپذیرد. مثلا a232443nkjn را هم میپذیر. چون نقطه شروع و پایان را درون قاعده محدود نکردیم پس این قاعده را به این تغییر میدهیم :
regex = /^[0123456789]{5,15}$/
اکنون فقط رشته های عددی که بین 5 تا 15 رقم را دارند میپذیرد. البته میتوان این را خلاصه تر کرد.
regex = /^[0-9]{5,15}$/
اینجا علامت - به معنای تا است. اینجا یعنی 0 تا 9. البته میتوان مثلا بجای 1234 هم نوشت 1 تا 4!
مسئله : قاعده ای تعریف کنید که فقط کلمات لاتین را بپذیرد.
میدانیم کلمه فقط از حروف لاتین ساخته شده است. نه از اعداد و یا سایر کاراکترها. پس درون براکت فقط کاراکترهای حروف لاتین را قرار میدهیم.
regex = /^[abcdefghijklmnopqrstuvwxyz]$/
دقت کنید کل این براکت فقط بجای آن یک نقطه عمل میکند. پس قاعده بالا فقط کلمه یک حرفی را میپذیرد.
regex = /^[abcdefghijklmnopqrstuvwxyz]+$/
اینجا تمام کلماتی که حداقل یک حرف دارند را میپذیرد. البته گفتیم قاعده به بزرگی و کوچکی حروف حساس است. پس دو راه دارم :
regex = /^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]+$/
راه دوم استفاده از modifier i است.
regex = /^[abcdefghijklmnopqrstuvwxyz]+$/i
بین حروف هم میتوان از - یا تا استفاده کرد. مثلا گفت a-z به معنی a تا z است.
regex = /^[a-z]+$/i
یا بدون modifier :
regex = /^[a-zA-Z]+$/
اکنون این قاعده فقط کلمات را میپذیرد. برای اینکه ارقام را هم بپذیرد :
regex = /^[a-zA-Z0-9]+$/
دقت کنید بجای ارقام و حروف سایر کاراکترها مانند نقطه و یا هر کاراکتر دیگری را درون براکت گذاشت.
وقتی در ابتدای شروع براکت کاراکتر ^ را قرار دهیم، دقیقا کار براکت برعکس میشود. دقت کنید کاراکتر ^ در ابتدای براکت با ^ در ابتدای قاعده بحث کاملا متفاوتی دارد. مثلا در قاعده زیر :
regex = /^[0-9]+$/
رشته هایی که فقط شامل ارقام عددی باشند را میپذیرد ولی قاعده زیر :
regex = /^[^0-9]+$/
فقط رشته هایی را میپذیرد که شامل ارقام عددی نباشند.
مثلا ما میخواهیم درون عبارات با قاعده خود از کاراکترهایی مانند نقطه ، علامت سوال، اسلش و هر کاراکتر رزرو شده دیگه ای که در عبارات باقاعده معنای خاصی دارند، استفاده کنیم. تنها کاری که باید کنیم قبل از آن کاراکتر \ میگذاریم.
مثلا :
regex = /^[a-zA-Z0-9\.\[\]\{\}\/]+$/
در این جا علاوه بر حروف و ارقام ؛ رشته های دارای کاراکترهای نفطه و برکت و گیومه و اسلش را هم میپذیریم.
regex = /^_\+/
این قاعده فقط رشته هایی را میپذیرد که با +_ شروع میشوند.
برخی حروف اگر بعد از \ بیایند درون دستورات عبارات با قاعده معنای خاصی دارند. مثلا برای اینکه کنترل کنیم که فقط رشته های عددی پذیرفته شوند از قاعده زیر استفاده میکردیم :
regex = /^[0-9]+$/
روش دیگر استفاده از d\ است :
regex = /^\d+$/
این دو قاعده معادل همدیگر هستند.
برعکس d\ میشود D\ : یعنی دو قاعده زیر معادل یکدیگر هستند.
regex = /^[0-9]+$/ regex = /^\D+$/
هر دو این قاعده فقط رشته هایی را میپذیرند که هیچ رقم عددی درون آن نباشد.
دقت کنید که d خلاصه شده digit است.
برای کلمات هم w\ و W\ را داریم که برعکس یکدیگر عمل میکنند.
حروف w\ : به معنای کاراکتری است که فقط شامل حروف لاتین است.
regex = /^[a-zA-Z]+$/ regex = /^\w+$/
حروف W\ : به معنای کاراکتری است که فقط شامل غیر حروف لاتین است.
regex = /^[^a-zA-Z]+$/ regex = /^\W+$/
حروف s\ : به معنای کاراکتر اسپیس است. شامل تمام اسپیسهاست.
regex = /^[ ]+$/ regex = /^\s+$/
regex = /^[^ ]+$/ regex = /^\S+$/
کاراکترهایی که بعد از پایان قاعده قرار میدهیم. و هرکدام حالت قاعده را تغییر میدهد. مانند i.
مدیفایر i : برای کنترل اینکه قاعده ایجاد شده نسبت به حروف بزرگ و کوچک حساس نباشد استفاده میکنند.
regex = /^a.+$/i
در این حالت abas و Abas توسط این قاعده پذیرفته میشوند و پاسخ true برمیگردد.
مدیفایر s : با کمک این مدیفایر، قاعده رشته ورودی را یک خط در نظر میگیرد. مثلا :
$input = 'I am abbas bagheri'; $regex = 'abbas.bagheri/s'; echo preg_match($regex , $input); // output : 1 or true
مدیفایر m : با این مدیفایر، رشته دریافتی را بر اساس خط به خط بررسی میکند. و برای خط جداگانه بررسی میکند.
$input = 'abax abei abef abld ddde" $regex = "ab.{2}/m'; echo preg_match($regex , $input);
در مثال بالا قاعده رشته را خط به خط بررسی میکند یکبار برای abax یک بار برای abei و تا خط آخر و خروجی یک آرایه برمیگرداند.
بررسی شماره تلفن همراه کاربر :
شماره تلفن به دو صورت وارد میشود یا 09015827703 یا 98901827703+. یا با 0 شروع میشود یا 98+
phoneRegex = /^(\+98|0)/
رقم بعدی 9 است :
phoneRegex = /^(\+98|0)9/
باتوجه به شماره های اپراتورهایی که در ایران داریم رقم بعدی 0 1 2 3 و 9 باشد :
phoneRegex = /^(\+98|0)9[01239]/
و سپس شماره تلفن با 8 کاراکتر عددی دیگر پایان میابد :
var phoneRegex = /^(\+98|0)9[01239][0-9]{8}$/ input = '09015827703' phoneRegex.exec(input); // return true var phoneRegex = /^(\+98|0)9[01239][0-9]{8}$/ input = '09515827703' phoneRegex.exec(input); // return false
امیدوارم پست مفید بوده باشه.