Regular Expressions (RegEx) - From Fear to Mastery
"The Search Engine for Your Code"
প্রোগ্রামিংয়ে আমাদের সব সময় টেক্সট খুঁজতে হয়। "এই ইমেইলটা কি ভ্যালিড?" "টেক্সটের সব নাম্বার বের করে আনো।" "সব স্পেস সরিয়ে দাও।"
সাধারণ if-else বা লুপ দিয়ে এগুলো করতে গেলে কোড পাহাড় সমান হয়ে যাবে। RegEx দিয়ে এগুলো এক লাইনে করা সম্ভব। এটি একটি প্যাটার্ন ম্যাচিং ল্যাঙ্গুয়েজ।
⭐ ১. Regex তৈরি ও বেসিক সিনট্যাক্স
Regex লেখার দুটি উপায় আছে:
A) Literal Syntax (স্ল্যাশ এর ভেতরে) - Recommended ✅
যখন তুমি জানো প্যাটার্ন ফিক্সড থাকবে।
const regex = /hello/gi;
// g = global (সবগুলো খুঁজবে)
// i = case insensitive (বড়/ছোট হাতের তফাৎ করবে না)
B) Constructor Syntax (ডাইনামিক) ⚙️
যখন প্যাটার্নটি কোনো ভেরিয়েবল থেকে আসবে।
const searchTerm = "hello";
const regex = new RegExp(searchTerm, "gi");
⭐ ২. Flags: প্যাটার্নের মুড সুইং 🚩
ফ্ল্যাগগুলো বলে দেয় সার্চটা কীভাবে হবে।
| Flag | Meaning | কাজ কী? |
|---|---|---|
| g | Global | প্রথমটা পাওয়ার পর থামবে না, পুরো টেক্সটে খুঁজবে |
| i | Insensitive | A এবং a কে সমান মনে করবে |
| m | Multiline | ^ এবং $ প্রতিটি লাইনের শুরু/শেষে কাজ করবে |
⭐ ৩. Character Classes: কী খুঁজছি?
নির্দিষ্ট অক্ষর না খুঁজে আমরা টাইপ খুঁজতে পারি।
\d
যেকোনো সংখ্যা [0-9]
\w
a-z, A-Z, 0-9, _
\s
স্পেস, Tab, Newline
.
নিউলাইন বাদে যেকোনো ক্যারেক্টার
বড় হাতের মানেই উল্টো (Not): \D (সংখ্যা ছাড়া), \W (স্পেশাল ক্যারেক্টার), \S (স্পেস ছাড়া)
const text = "Phone: 01711";
const regex = /\d+/g; // সব সংখ্যা খোঁজো
console.log(text.match(regex)); // ["01711"]
⭐ ৪. Anchors: সীমানা নির্ধারণ ⚓
জুনিয়ররা প্রায়ই contains এর মতো সার্চ করে, কিন্তু সিনিয়ররা পজিশন ঠিক করে দেয়।
- ^ (Caret): স্ট্রিংয়ের শুরুতে থাকতে হবে
- $ (Dollar): স্ট্রিংয়ের শেষে থাকতে হবে
- \b (Word Boundary): শব্দের সীমানা
const text = "This is a cat.";
/cat/.test(text); // true (মাঝখানে থাকলেও পাবে)
/^cat/.test(text); // false (শুরুতে নেই)
/cat$/.test(text); // false (শেষে নেই, কারণ শেষে ডট . আছে)
/\bcat\b/.test(text); // true (আলাদা শব্দ হিসেবে আছে)
⭐ ৫. Quantifiers: কয়টা চাই? (Greedy vs Lazy) 🔢
১ বা বেশি
০ বা বেশি
০ বা ১
ঠিক ৩ বার
৩ থেকে ৫ বার
⚠️ The Greedy Trap (Senior Concept)
Regex বাই ডিফল্ট Greedy (লোভী)। সে যতটা পারে বেশি ম্যাচ করার চেষ্টা করে।
const html = "Hello";
// Greedy (<.+>): প্রথম < থেকে শেষ > পর্যন্ত পুরোটাই নিয়ে নেবে
// Lazy (<.+?>): ? দেওয়ার মানে হলো "সবচেয়ে কম ম্যাচ করো"
⭐ ৬. Groups & Capturing: আলাদা করে ধরা 🕸️
ব্র্যাকেট () ব্যবহার করে আমরা গ্রুপ করতে পারি এবং সেই অংশটুকু আলাদা করতে পারি।
const date = "2024-10-25";
const regex = /(\d{4})-(\d{2})-(\d{2})/; // (Year)-(Month)-(Day)
const match = date.match(regex);
// match[0] = পুরোটা "2024-10-25"
// match[1] = "2024" (Group 1)
// match[2] = "10" (Group 2)
// match[3] = "25" (Group 3)
Non-capturing Group (?:): শুধু গ্রুপ করতে চাই কিন্তু রেজাল্টে আলাদা করে সেভ করতে না চাও।
⭐ ৭. Lookahead & Lookbehind (Ninja Skills) 🥷
Positive Lookahead (?=...):
"সামনে যদি এটা থাকে, তবেই ম্যাচ করো।" Java(?=Script) → Java ম্যাচ করবে শুধু যদি পরে Script থাকে
Negative Lookahead (?!...):
"সামনে যদি এটা না থাকে।" Java(?!Script) → Java ম্যাচ করবে যদি পরে Script না থাকে
Real Use Case: Password Validation
const hasNumber = /(?=.*\d)/;
// সামনে তাকিয়ে দেখো কোথাও কোনো digit (\d) আছে কিনা।
⭐ ৮. Real-World Recipes (Copy-Paste Ready) 🍲
🔥 ১. ইমেইল ভ্যালিডেশন
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
🔥 ২. বাংলাদেশী ফোন নম্বর
const bdPhone = /^(?:\+8801|01)[3-9]\d{8}$/;
🔥 ৩. স্ট্রং পাসওয়ার্ড চেকার
const strongPass = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*]).{8,}$/;
🔥 ৪. টেক্সট থেকে URL বের করা
const urlRegex = /https?:\/\/[^\s]+/g;
⭐ ৯. Advanced Methods: match, replace, test
const str = "Price is 500 and Vat is 50";
// ১. আছে কি নেই? (Boolean)
console.log(/\d+/.test(str)); // true
// ২. সব বের করে আনো (Array)
console.log(str.match(/\d+/g)); // ["500", "50"]
// ৩. রিপ্লেস করা (Powerful)
console.log(str.replace(/\d+/g, "#")); // "Price is # and Vat is #"
// ৪. Swap Words (First Last -> Last, First)
const name = "John Doe";
console.log(name.replace(/(\w+)\s(\w+)/, "$2, $1")); // "Doe, John"
⭐ ১০. Performance & ReDoS (Senior Warning) ⚠️
Regex স্লো হতে পারে যদি ভুলভাবে লেখা হয়। একে বলা হয় Catastrophic Backtracking।
❌ /(a+)+/ → Bad (নেস্টেড কুয়ান্টিফায়ার)
✅ /a+/ → Good
🧠 ১১. Senior Interview Questions
Q1: search() এবং match() এর পার্থক্য কী?
উত্তর: search() শুধু ইনডেক্স রিটার্ন করে। match() পুরো অ্যারে রিটার্ন করে (যদি g ফ্ল্যাগ থাকে)।
Q2: Greedy এবং Lazy ম্যাচিং এর উদাহরণ দিন?
উত্তর: .* হলো গ্রিডি, .*? হলো লেজি। HTML ট্যাগ পার্সিংয়ের সময় Lazy ব্যবহার করতে হয়।
Q3: \b কেন গুরুত্বপূর্ণ?
উত্তর: এটি ভুল ম্যাচ আটকায়। /\bcat\b/ দিলে শুধু আলাদা "cat" শব্দটি ম্যাচ হবে।
🚀 অধ্যায় ১৯ সারাংশ (Checklist)
- ✓Basics: ^ (শুরু), $ (শেষ), . (সব), \d (সংখ্যা)
- ✓Quantifiers: + (১+), * (০+), ? (অপশনাল)
- ✓Grouping: () দিয়ে ধরা এবং $1, $2 দিয়ে রিপ্লেস করা
- ✓Lookahead: (?=...) দিয়ে শর্ত চেক করা
- ✓Methods: test (চেক), match (খোঁজা), replace (বদলানো)
Next Step: আমরা ডেটা এবং লজিক শিখেছি। কিন্তু মেমোরিতে এই ডেটাগুলো থাকার সময় আবর্জনাও তৈরি হয়। জাভাস্ক্রিপ্ট কীভাবে মেমোরি পরিষ্কার করে? মেমোরি লিক কেন হয়? পরের অধ্যায়: "Memory Management & Garbage Collection"。