রেগুলার এক্সপ্রেশন -এ শেষ।

আগের লেখায়  আমরা রেগুলার এক্সপ্রেশনের বেসিক অনেক কিছুই দেখেছিলাম, এই লিখার মাধ্যমে আমরা এর শেষ করবো। প্রথমে আমাদের গিনিপিগ স্ট্রিং কে আবার নিয়ে আসি।

Mr. Alu and mr. Potol are friends since 2008. They study at the same university in the session 2008-2009.

গত লেখায় আমরা এই গিনিপিগ স্ট্রিং থেকে বছর বের করার প্যাটার্ন লিখেছিলাম, যা ছিলো এরকমঃ

var str = 'Mr. Alu and mr. Potol are friends since 2008. They study at the same university in the session 2008-2009.';
var pattern = /\d{4}/;
var matches = str.match(pattern);
console.log(matches);

/* Output in console*/
 ["2008"]

এখানে ফলাফল হিসেবে দেখতে পাচ্ছি শুধু 2008 কে দেখাচ্ছে যদিও আমাদের স্ট্রিং-এ আরও কয়েকটা বছর রয়েছে। সাধারনভাবে রেগুলার এক্সপ্রেশনে প্রথম মিলটি পেলেই খোঁজা বন্ধ করে দেয়। যদি আমাদের সবগুলা ম্যাচিং বা মিলগুলো দরকার হয় তাহলে আমাদেরকে আলাদাভাবে বলে দিতে হয়। এই বলে দেবার কাজটি যা দিয়ে করা হয় তাকে রেগুলার এক্সপ্রেশনে বলে মডিফায়ার। জাভাস্ক্রিপ্টে হাতেগোনা কয়েকটা মডিফায়ার ফ্ল্যাগ আছে। যেমনঃ

মডিফায়ার ফ্ল্যাগ অর্থ
g g মানে গ্লোবাল অর্থাৎ একবার মিল পেলে খোঁজা বন্ধ না করে সম্পূর্ণ স্ট্রিং-এ  খুঁজবে।
i ইন-কেইস সেনসিটিভ মানে ছোট বড় সকল বর্ণ একই বিবেচনা করবে।
m m মানে মাল্টিলাইন। মাল্টিলাইনযুক্ত স্ট্রিং-এর প্রতিটি লাইনের শুরু ও শেষ আলাদাভাবে বিবেচনা করবে।

একই প্যাটার্নে একাধিক মডিফায়ার এক সাথে ব্যবহার করা যায়। এখন আমরা যদি আমাদের গিনিপিগ স্ট্রিং থেকে সবগুলো বছর বের করতে চাই তাহলে প্যাটার্নটি হবেঃ

var str = 'Mr. Alu and mr. Potol is closed friend since 2008. They are studying in same university in the session 2008-2009.';
var pattern = /\d{4}/g;
var matches = str.match(pattern);
console.log(matches);

/* Output in console*/
["2008", "2008", "2009"]

এখানে শেষ স্ল্যাশের পরে g হলো মডিফায়ার ফ্ল্যাগ। অনুরুপভাবে, আমরা যদি Mr. কতবার আছে তা বের করতে চাই তাহলে প্যাটার্নটি হবেঃ

var str = 'Mr. Alu and mr. Potol are friends since 2008. They study at the same university in the session 2008-2009.';
var pattern = /mr\./gi;
var matches = str.match(pattern);
console.log(matches);

/* Output in console*/
["Mr.", "mr."]

এখানে দুটো বিষয় লক্ষ্যনীয়,

১। যেহেতু Mr. এবং mr. দুটোই আছে, তাই ফ্ল্যাগ g এর সাথে i ব্যবহার করেছি,  এর ফলে কেইস বিবেচনা করবে না।

২। যেহেতু ডট (.) একটি বিশেষ ক্যারেক্টার কিন্তু আমরা লিটার‍্যালি বিবেচনা করতে চাচ্ছি তাই একে স্কেপ করা লাগবে।বিশেষ ক্যারেক্টারকে স্কেপ করার জন্যে তার আগে একটা ব্যাকওয়ার্ড স্ল্যাশ দিতে হয়।

আচ্ছা, এখানে যদি আমরা ইন-কেইস সেনসিটিভ মডিফায়ার i ব্যবহার না করি তাহলে কি প্যাটার্নটি তৈরি করা যাবে? হ্যাঁ যাবে, সেক্ষেত্রে আমাদের দুইটি প্যাটার্ন লাগবে। একটি প্যাটার্ন লাগবে Mr. জন্যে এবং আরেকটি প্যাটার্ন লাগবে mr. এর জন্যে। একই প্যাটার্ন-এ এরকম এক বা একাধিক সাব-প্যাটার্ন লেখা যায় এবং সাব-প্যাটার্নগুলো লিখতে হয় প্রথম বন্ধনির ভিতরে। সাব-প্যাটার্ন ব্যবহার করে উপরের প্যাটার্নটি নতুন করে লিখলে নিচের মতো হবে। লক্ষ্যনীয় যে, সাব-প্যাটার্ন দুটির মাঝে OR সাইন | ব্যবহার করা হয়েছে যার মানে দুটির মাঝে যেকোনো একটি।

var str = 'Mr. Alu and mr. Potol are friends since 2008. They study at the same university in the session 2008-2009.';
var pattern = /(Mr\.|mr\.)/g;
var matches = str.match(pattern);
console.log(matches);

/* Output in console*/
["Mr.", "mr."]

রেগুলার এক্সপ্রেশনে প্রথম বন্ধনির ভিতরে এরকম সাব-প্যাটার্নের আলাদা গুরুত্ব রয়েছে এবং সেটি হচ্ছে মূল প্যাটার্নের মিল বা ম্যাচিং গুলার সাথে সাব-প্যাটার্নের ম্যাচিংগুলোও আলাদা ভাবে পাওয়া যায় বা ক্যাপচার করা যায়। এ জন্যে রেগুলার এক্সপ্রেশনে এদেরকে ক্যাপচারিং গ্রুপ বলে । ধরা যাক, আমরা আমাদের গিনিপিগ স্ট্রিং-এ কি কি নাম আছে সেগুলো বের করতে চাচ্ছি এবং নাম বলতে আমরা বুঝি যাদের প্রথমে Mr./mr. থাকবে, তারপরে একটি স্পেস, তারপরে কিছু ওয়ার্ড ক্যারেক্টার এবং শেষ হবে একটি স্পেসের মাধ্যমে অর্থাৎ প্যাটার্নটি হবে

var str = 'Mr. Alu and mr. Potol are friends since 2008. They study at the same university in the session 2008-2009.';
var pattern = /(Mr\.|mr\.)\s\w+\s/g;
var matches = str.match(pattern);
console.log(matches);

/* Output in console*/
["Mr. Alu ", "mr. Potol "]

/*Actual Output*/
[ Match 1: "Mr. Alu ", Group1: "Mr."
  Match 2: "Mr. Potol ", Group2: "mr."]

যদিও জাভাস্ক্রিপ্টে match ফাংশন ক্যাপচারিং গ্রুপের মিলগুলো দেখায় না কিন্তু এর আসল ফলাফল হবে Actual Output সেকশনে দেখানো ফলাফলের মতো। আমাদের অনেক সময় ক্যাপচারিং গ্রুপের মিলগুলো দরকার পরে না কিন্তু আমরা শুধু সাব-প্যাটার্ন ব্যবহার করতে চাই, তাহলে প্রথম বন্ধনির পরে ?: দিতে হয় যাকে বলে নন-ক্যাপচারিং গ্রুপ। প্রকৃতপক্ষে জাভাস্ক্রিপ্টে match ফাংশন সুনির্দিষ্ট ভাবে এই নন-ক্যাপচারিং গ্রুপ মুডে কাজ করে। যাই হোক, নন-ক্যাপচারিং মুডে উপরের প্যাটার্নটি হবে

var str = 'Mr. Alu and mr. Potol are friends since 2008. They study at the same university in the session 2008-2009.';
var pattern = /(?:Mr\.|mr\.)\s\w+\s/g;
var matches = str.match(pattern);
console.log(matches);

/* Output in console*/
["Mr. Alu ", "mr. Potol "]

রেগুলার এক্সপ্রেশনে প্রথম বন্ধনি এবং এর ভিতরের সাব-প্যাটার্নের আরো কিছু ব্যবহার আছে। যেমন, কখনো কখনো আমাদের প্রত্যাশিত মিলটি বের করার জন্যে স্ট্রিং-এর সামনে তাকিয়ে দেখতে হয় যে আমরা যেই রকম ম্যাচিং চাচ্ছি সেটা আছে কিনা অর্থাৎ আমরা কন্ডিশনালি পরীক্ষা করে সামনে এগুতে চাই। ধরা যাক, আমরা আমাদের গিনিপিগ স্ট্রিং-এ শিক্ষাবর্ষের প্রথম বছরটি বের করতে চাই, অন্য বছরগুলো নয়।  শিক্ষাবর্ষ মানে দুটি বছর একটি ড্যাশ দিয়ে আলাদা করা যেমন, শিক্ষাবর্ষ 2008-2009 এ আমরা 2008 কে বের করতে চাচ্ছি। তো আমাদের নিশ্চিত হতে হতে যে 2008 এর পরে একটি ড্যাশ এবং ঠিক তার পরে আরেকটি বছর আছে। তার মানে আমরা যদি স্ট্রিং -এ  কোনো বছর পাই তাহলে আমরা সামনে তাকিয়ে দেখবো ঠিক এর পরে কোনো ড্যাশ এবং আরেকটি বছর আছে কিনা কিন্তু এই ড্যাশ এবং বছরটিকে আমরা আমাদের প্রাপ্ত ম্যাচিং বা মিলে চাচ্ছি না। আমরা শুধু দেখতে চাচ্ছি বেটা আছে কি নাই। রেগুলার এক্সপ্রেশনে এই ধরনের শর্ত দিতে হয় প্রথম বন্ধনির পরে ?= দিয়ে যা দেখতে অনেকটা নন-ক্যাপচারিং গ্রুপের মতো যেখানে ?:  পরিবর্তে ?= দিতে হয়। রেগুলার এক্সপ্রেশনে একে বলে লুক-অ্যাহেড (lookahead) । সুতারাং প্যাটার্নটি লিখা যাক

var str = 'Mr. Alu and mr. Potol are friends since 2008. They study at the same university in the session 2008-2009.';
var pattern = /\d{4}(?=-\d{4})/g;
var matches = str.match(pattern);
console.log(matches);

/* Output in console*/
["2008"]

আমরা দেখতে পাচ্ছি আমাদের প্রাপ্ত ফলাফলের ম্যাচিং বা মিলে -2009 নাই কারণ লুকঅ্যাহেড প্যাটার্নটি শুধুই শর্তটি যাচাই করে কিন্তু ফলাফলে প্রাপ্ত ম্যাচিংকে প্রভাবিত করে না। লুকঅ্যাহেডের ঠিক বিপরীত হচ্ছে নেগেটেড লুকঅ্যাহেড (negated lookahead) যা শুরু করতে হয় প্রথম বন্ধনির পরে ?! দিয়ে যা কাজ করে লুক-অ্যাহেডের ঠিক উল্টা নিয়মে। প্রথম বন্ধনির ব্যবহারের একটা তালিকা এক নজরে দেখে নেইঃ

নিয়মনামপ্রাপ্ত ম্যাচিংএ প্রভাব
(PATTERN)ক্যাপচারিং গ্রুপ  হ্যাঁ
(?:PATTERN) নন-ক্যাপচারিং গ্রুপ হ্যাঁ
(?=PATTERN)লুকঅ্যাহেড না
(?!PATTERN)নেগেটেড লুকঅ্যাহেড না

রেগুলার এক্সপ্রেশনে আরও কিছু বিশেষ ক্যারেক্টার আছে যেগুলোও প্রাপ্ত ম্যাচিং এর উপর কোনো প্রভাব না ফেলে কাজ করে যাদেরকে পজিশনিং ক্যারেক্টার বলে। যেমন,  স্ট্রিং-এর শুরু কিংবা শেষ অবস্থান।  উদাহরণস্বরূপ, যদি আমরা আমাদের গিনিপিগ স্ট্রিং-এর  শুরুতে যে Mr. টি আছে শুধু সেটি বের করতে চাই। তাহলে প্যাটার্নটি হবে

var str = 'Mr. Alu and mr. Potol are friends since 2008. They study at the same university in the session 2008-2009.';
var pattern = /^Mr./g;
var matches = str.match(pattern);
console.log(matches);

/* Output in console*/
["Mr."]

শুরু বুঝাতে বিশেষ ক্যারেক্টারটি হচ্ছে ^ এবং শেষ বুঝাতে বিশেষ ক্যারেক্টারটি হচ্ছে $। অবস্থান সম্পর্কিত আরেকটি বিশেষ নিয়ম হচ্ছে \b যাকে ওয়ার্ড বাউন্ডারি বলে। ওয়ার্ড-বাউন্ডারি হচ্ছে এমন একটি পজিশন বা অবস্থান যেখানে একটি ওয়ার্ড ক্যারেক্টারের ঠিক পরে একটি নন-ওয়ার্ড ক্যারেক্টার থাকে। যেমন, অ্যালফাবেটের পরে স্পেস। শুধু মনে রাখতে হবে কোনো পজিশনিং ক্যারেক্টারই প্রাপ্ত ম্যাচিং-এর উপর প্রভাব ফেলে না।

আমরা মোটামুটি রেগুলার এক্সপ্রেশনের সবগুলা নিয়মই আলোচনা করে ফেলেছি। লেখাটিও শেষ করা দরকার।  একটি বিষয় বলে শেষ করবো। প্রথম লেখায় আমরা যে কোয়ান্টিফায়ারগুলো দেখেছি, সেগুলো সবগুলোই লোভী বা গ্রিডি অর্থাৎ ম্যাচিংটি যতোটা সম্ভব বড় করে। যেমন, 20.* প্যাটার্নটির মানে হচ্ছে 20 এর পরে যেকোনো ক্যারেক্টার অসংখ্য বার থাকবে। এটি যদি আমাদের গিনিপিগ স্ট্রিং-এ প্রয়োগ করি তাহলে প্রাপ্ত ম্যাচিং-এর সংখ্যা হবে একটি এবং ম্যাচিংটি হবে দীর্ঘ 008. They are studying in same university in the session 2008-2009. আমরা চাইলে গ্রিডি থেকে নন-গ্রিডি বা লেজি করে দিতে পারি, তার ফলে প্রাপ্ত ম্যাচিং-এর দৈর্ঘ্য ছোট করে ম্যাচিং-এর সংখ্যা যতগুলো সম্ভব বের করবে। গ্রিডি থেকে নন-গ্রিডি করতে কোয়ান্টিফায়ার ক্যারেক্টারের পরে একটি অতিরিক্ত প্রশ্নবোধক চিহ্ন ? দিতে হবে। যেমন, 20.* এর নন-গ্রিডি রূপ হচ্ছে 20.*?  অনুরুপভাবে, কোয়ান্টিফায়ার ক্যারেক্টার + এর পরে ? বসিয়ে গ্রিডি থেকে নন-গ্রিডি করতে পারি।

/* Greedy mode */
var str = 'Mr. Alu and mr. Potol are friends since 2008. They study at the same university in the session 2008-2009.';
var pattern = /20.*/g;
var matches = str.match(pattern);
console.log(matches);

/* Output in console*/
["2008. They study at the same university in the session 2008-2009."]

/* Non greedy or lazy mode */
var str = 'Mr. Alu and mr. Potol are friends since 2008. They study at the same university in the session 2008-2009.';
var pattern = /20.*?/g;
var matches = str.match(pattern);
console.log(matches);

/* Output in console*/
["20", "20", "20"]

অবশেষে সংক্ষিপ্ত রেগুলার এক্সপ্রেশনের লেখাটি শেষ হলো। ধন্যবাদ।

1 thought on “রেগুলার এক্সপ্রেশন -এ শেষ।

  1. Pingback: রেগুলার এক্সপ্রেশন -এ শুরু। | যেমন ইচ্ছে লেখার আমার কবিতার খাতা।

Leave a Reply

Your email address will not be published. Required fields are marked *