Skip to content
Regex চিটশিট
Tools

Regex চিটশিট

নতুন

regular expression টোকেন ও ফ্ল্যাগের অনুসন্ধানযোগ্য রেফারেন্স।

Live regex tester

Type a pattern and a test string — matches highlight instantly, with every capture group broken out below.

/ /
Flags
Matches
Capture groups

Common regex patterns

Battle-tested patterns — load one into the tester to see it run, or copy it straight out.

Email address
[\w.+-]+@[\w-]+\.[\w.-]+
URL (http/https)
https?:\/\/[^\s]+
US phone number
\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}
Date (YYYY-MM-DD)
(\d{4})-(\d{2})-(\d{2})
Time (24-hour)
([01]?\d|2[0-3]):[0-5]\d
IPv4 address
\b(?:\d{1,3}\.){3}\d{1,3}\b
Hex color
#(?:[0-9a-fA-F]{6}|[0-9a-fA-F]{3})\b
Slug / username
[a-z0-9]+(?:-[a-z0-9]+)*
Whole number / integer
-?\d+
Strong password (8+, mixed)
(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}
Duplicate word
\b(\w+)\s+\1\b
Trailing whitespace
[ \t]+$

Regex cheat sheet

Every token, grouped with a quick example. Search by symbol or keyword; click any token to copy it.

Regex flavors: JavaScript, Python, Java, PCRE & grep

The tester above runs JavaScript regex. Most syntax is shared — here's what differs between engines.

FeatureJavaScriptPython (re)JavaPCRE / grep
Named group(?<name>…)(?P<name>…)(?<name>…)(?P<name>…)
Dotall (. matches \n)s flagre.DOTALL / (?s)Pattern.DOTALL(?s)
Ignore casei flagre.IGNORECASE / (?i)(?i) flag(?i) / grep -i
Lookbehind(?<=…) ES2018+SupportedSupportedgrep -P only
Backslash in source/\d/ literalr"\d" raw string"\\d" doubled\d
Find every matchstr.matchAll(/…/g)re.findall()Matcher.find()grep -o
POSIX class [[:digit:]]use \d insteaduse \d insteadsupportedsupported

Runs entirely in your browser. Nothing is uploaded.

উদাহরণসহ একটি regex চিট শিট — সঙ্গে লাইভ টেস্টার

এই regex চিট শিট প্রতিটি রেগুলার এক্সপ্রেশন টোকেনকে মাত্র এক সার্চ দূরে রাখে — এবং সাথে জুড়ে দেয় একটি লাইভ টেস্টার, যাতে টোকেন খুঁজে পাওয়ার সঙ্গে সঙ্গেই আপনি প্যাটার্নটি চেষ্টা করে দেখতে পারেন। একটি প্যাটার্ন টাইপ করুন, ফ্ল্যাগ বাছুন, একটি টেস্ট স্ট্রিং পেস্ট করুন — ম্যাচগুলো সঙ্গে সঙ্গে হাইলাইট হয় এবং নিচে প্রতিটি ক্যাপচার গ্রুপ আলাদা করে দেখানো হয়।

ইনস্টল করার কিছু নেই, অ্যাকাউন্ট তৈরিরও দরকার নেই: পুরো রেগুলার এক্সপ্রেশন রেফারেন্স আপনার ব্রাউজারেই চলে, তাই আপনি যে টেক্সট টেস্ট করেন তা কখনও আপলোড হয় না। কোনো বিজ্ঞাপন নেই, কোনো লগইন দেয়াল নেই, আর টেস্ট স্ট্রিংয়ের আকারেও কোনো সীমা নেই।

প্রতিটি regex টোকেন, উদাহরণসহ গোছানো

রেফারেন্সটি ঠিক সেই সিনট্যাক্সই কভার করে যা আপনি বাস্তবে ব্যবহার করেন: ক্যারেক্টার ক্লাস (\d, \w, \s এবং [a-z]-এর মতো কাস্টম সেট), অ্যাংকর ও বাউন্ডারি (^, $, \b), কোয়ান্টিফায়ার (*, +, ?, {n,m} এবং তাদের lazy রূপ), গ্রুপ ও অল্টারনেশন, লুকঅ্যাহেড ও লুকবিহাইন্ড, ফ্ল্যাগ g i m s u y, এবং literal ডট ও স্ল্যাশের জন্য দরকারি এস্কেপগুলো।

প্রতিটি এন্ট্রির সাথে থাকে একটি ছোট, সুনির্দিষ্ট উদাহরণ — \bcat\b ‘cat’ শব্দটি ম্যাচ করে কিন্তু ‘category’-কে করে না — ফলে অর্থটা মাথায় গেঁথে যায়। প্রতীক বা কীওয়ার্ড দিয়ে regex টোকেন সার্চ করুন এবং যেকোনো একটিতে ক্লিক করে কপি করে নিন।

প্যাটার্ন তৈরি করার সময়ই টেস্ট করুন

স্ট্যাটিক চিট শিট আপনাকে বলতে পারে না আপনার প্যাটার্নটি আসলেই কাজ করছে কিনা। বিল্ট-ইন regex টেস্টার আপনার এক্সপ্রেশনটি লাইভ কম্পাইল করে, স্যাম্পল টেক্সটে প্রতিটি ম্যাচ হাইলাইট করে, এবং প্রতিটির জন্য নম্বরযুক্ত ও নামযুক্ত ক্যাপচার গ্রুপগুলো তালিকাবদ্ধ করে।

global, case-insensitive, multiline, dotall, Unicode ও sticky ফ্ল্যাগ টগল করুন এবং ফলাফল পাল্টাতে দেখুন। কোনো প্যাটার্ন ভুল হলে নীরবে ব্যর্থ হওয়ার বদলে আপনি একটি সহজ-বোধ্য এরর মেসেজ পান — আর কোনো প্যাটার্নকে রিয়েল টাইমে ম্যাচ করতে দেখাই regex শেখার সবচেয়ে দ্রুত উপায়।

সাধারণ regex প্যাটার্ন, কপি করার জন্য প্রস্তুত

কিছু প্যাটার্ন বারবার কাজে লাগে — ইমেইল ঠিকানা, URL, ফোন নম্বর, ISO তারিখ, IPv4 ঠিকানা, hex রং এবং শক্তিশালী পাসওয়ার্ড যাচাই। Common patterns অংশটি এদের প্রতিটির একটি যাচাইকৃত সংস্করণ দেয়: সরাসরি টেস্টারে লোড করে উদাহরণ টেক্সটে চলতে দেখুন, অথবা আপনার কোডে কপি করে নিন।

এগুলো এক-মাপ-সবার-জন্য নিয়ম নয়, বরং বাস্তবসম্মত শুরুর বিন্দু যা আপনি নিজের প্রয়োজনমতো মানিয়ে নিতে পারেন — আর ঠিক এই কারণেই এদের আপনার নিজের ডেটায় টেস্ট করা গুরুত্বপূর্ণ।

regex101.com ও regexr.com-এর সাথে এর তুলনা

regex101.com ওয়েবের সবচেয়ে জনপ্রিয় ডেডিকেটেড regex টুল — আর যথার্থ কারণেই। এটি ছয়টি regex ফ্লেভার সমর্থন করে (PCRE, Python re, Golang, Java, .NET এবং JavaScript), প্যাটার্নের প্রতিটি টোকেনের জন্য একটি টোকেন-বাই-টোকেন ব্যাখ্যা প্যানেল দেখায় এবং ম্যাচ হিস্ট্রি রাখে। জটিল প্রোডাকশন প্যাটার্ন ডিবাগ করলে বা কোনো প্যাটার্ন PHP ও Python-এ একইভাবে কাজ করছে কিনা যাচাই করতে চাইলে regex101 হলো সঠিক টুল। regexr.com অনুরূপ অভিজ্ঞতা দেয়, সাথে কমিউনিটির অবদান রাখা প্যাটার্নের একটি পাবলিক লাইব্রেরি।

এই UtiloKit পেজটি ওয়ার্কফ্লোর ভিন্ন একটি জায়গায় বসে। এটি একই স্ক্রিনে একটি সার্চযোগ্য টোকেন রেফারেন্স টেবিল এবং একটি লাইভ টেস্টার একসাথে রাখে, যা সেই সাধারণ পরিস্থিতির জন্য অপ্টিমাইজড যেখানে আপনি মোটামুটি জানেন কী দরকার কিন্তু সঠিক সিনট্যাক্স মনে করতে পারছেন না। আপনি পেজে আসেন, টোকেনটি খোঁজেন, একটি দ্রুত টেস্ট স্ট্রিং পেস্ট করেন এবং আবার এডিটরে ফিরে যান — কোনো ট্যাব-অদলবদল নেই, অ্যাকাউন্ট নেই, বিজ্ঞাপন নেই। যেসব ডেভেলপার লুকবিহাইন্ড (?<=…) নাকি (?<!…) ব্যবহার করে তা মনে করার জন্যই দিনে কয়েক ডজন বার regex101.com খোলেন, তাদের জন্য একটি ডেডিকেটেড সার্চযোগ্য রেফারেন্স মাপা যায় এমনভাবে দ্রুততর। দুটোই ব্যবহার করুন: গভীর ডিবাগিংয়ের জন্য regex101, আর দ্রুত খোঁজার জন্য এই পেজ।

regex ফ্লেভার: JavaScript, Python, Java, PCRE ও grep

বেশিরভাগ regex সিনট্যাক্স পোর্টেবল, কিন্তু ইঞ্জিনগুলো খুঁটিনাটিতে ভিন্ন হয়। এখানকার টেস্টার JavaScript regex ব্যবহার করে, যা Node.js ও ব্রাউজারের মতোই একই ফ্লেভার। Python-এর re মডিউল r"\d+"-এর মতো raw string চায় এবং গ্রুপের নাম দেয় (?P<name>…); Java-তে string literal-এ ব্যাকস্ল্যাশ দ্বিগুণ করতে হয়; PCRE (PHP এবং grep -P) সবচেয়ে বেশি ফিচার-সমৃদ্ধ; আর POSIX grep -E-র নিজস্ব এস্কেপিং খুঁতি রয়েছে।

ফ্লেভার টেবিলটি প্রতিটি ইঞ্জিনে named group, dotall, case-insensitivity, লুকবিহাইন্ড এবং ‘find all’ আলাদা করে তুলে ধরে, যাতে আপনি একটি python regex চিট শিট প্যাটার্নকে JavaScript-এ — বা উল্টো দিকে — কোনো চমক ছাড়াই সরাতে পারেন।

greedy বনাম lazy, এবং অন্যান্য ফাঁদ

দুটো জিনিস প্রায় সবাইকে বিভ্রান্ত করে। প্রথমত, কোয়ান্টিফায়ার greedy: .+ যতটা পারে ততটা দখল করে, তাই একটিমাত্র HTML ট্যাগ ম্যাচ করতে সাধারণত আপনার দরকার হয় lazy .+?। দ্বিতীয়ত, মেটাক্যারেক্টার এস্কেপ করতে ভুলে যাওয়া — খালি . যেকোনো ক্যারেক্টার ম্যাচ করে, অথচ \. একটি literal ডট ম্যাচ করে, তাই দামের regex-এ দরকার হয় \d+\.\d{2}

কাজ করার সময় চিট শিটটি খোলা রাখুন, তাহলে এগুলো আর চমক থাকবে না।

লুকঅ্যাহেড, লুকবিহাইন্ড ও non-capturing গ্রুপ

লুকঅ্যারাউন্ড অ্যাসারশন আপনাকে চারপাশের ক্যারেক্টার দখল না করেই তাদের ওপর ভিত্তি করে একটি ম্যাচ শর্তসাপেক্ষ করতে দেয়। একটি পজিটিভ লুকঅ্যাহেড (?=…) কেবল তখনই একটি অবস্থান ম্যাচ করে যখন ভেতরের সাব-এক্সপ্রেশনটি ডানদিকে ম্যাচ করে — \d+(?= dollars) "50 dollars"-এর সংখ্যাটি ম্যাচ করে কিন্তু ম্যাচে dollars শব্দটি অন্তর্ভুক্ত করে না। এর বিপরীত, নেগেটিভ লুকঅ্যাহেড (?!…), কেবল তখনই ম্যাচ করে যখন পরবর্তী টেক্সট ম্যাচ করে না — \b(?!un)\w+ এমন শব্দ ম্যাচ করে যেগুলো un উপসর্গ দিয়ে শুরু হয় না। লুকবিহাইন্ড একইভাবে কাজ করে কিন্তু বাঁদিকে তাকায়: পজিটিভ লুকবিহাইন্ড (?<=\$)\d+ এমন সংখ্যা ম্যাচ করে যার ঠিক আগে একটি ডলার চিহ্ন থাকে, আর নেগেটিভ লুকবিহাইন্ড (?<!\d)\d+ এমন সংখ্যা ম্যাচ করে যার আগে আরেকটি সংখ্যা নেই। লুকঅ্যারাউন্ড টেক্সট দখল না করে অবস্থান পরীক্ষা করে বলে, ম্যাচকৃত সাবস্ট্রিং না ঘেঁটেই আপনি স্ট্রিংয়ের একই বিন্দুতে কয়েকটি একসাথে স্তূপ করতে পারেন।

Non-capturing গ্রুপ (?:…) আপনাকে একটি নম্বরযুক্ত ক্যাপচার স্লট তৈরি না করেই কোনো সাব-এক্সপ্রেশনে কোয়ান্টিফায়ার বা অল্টারনেশন প্রয়োগ করতে দেয়। এটি পারফরম্যান্সের জন্য গুরুত্বপূর্ণ — প্রতিটি capturing গ্রুপ ম্যাচ ফলাফলে স্টোরেজ বরাদ্দ করে, এবং লক্ষ লক্ষ স্ট্রিংয়ের ওপর একটি hot loop-এ সেই খরচ জমতে থাকে। এটি দুর্ঘটনাক্রমে নম্বর সরে যাওয়াও ঠেকায়: বিদ্যমান কোনো প্যাটার্নে যদি (?:https|ftp) যোগ করেন, তাহলে আপনি আগে থেকে যে গ্রুপগুলো এক্সট্র্যাক্ট করছিলেন সেগুলো নিজেদের অবস্থান ধরে রাখে। কাঠামোর জন্য গ্রুপ করা দরকার হলে, এক্সট্র্যাকশনের জন্য নয়, তখন non-capturing গ্রুপই সেরা অভ্যাস।

Named capturing গ্রুপ এটিকে আরও এগিয়ে নেয়, প্রতিটি গ্রুপকে এমন একটি লেবেল দিয়ে যা আপনি কোডে ব্যবহার করতে পারেন। JavaScript ও PCRE সিনট্যাক্স হলো (?<name>…), আর Python ব্যবহার করে (?P<name>…)(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})-এর মতো একটি তারিখ প্যাটার্ন আপনাকে match[1]-এর বদলে match.groups.year লিখতে দেয়, যা উদ্দেশ্য স্পষ্ট করে এবং positional indexing-এর ভঙ্গুরতা দূর করে। Named গ্রুপ named backreference হিসেবেও পাওয়া যায় (JavaScript-এ \k<name>, Python-এ (?P=name)), যা এমন প্যাটার্নের জন্য কাজে লাগে যেগুলোকে পুনরাবৃত্ত একটি মান নিশ্চিত করতে হয় — যেমন একটি HTML open ট্যাগ ম্যাচ করা এবং যাচাই করা যে এর close ট্যাগে একই এলিমেন্টের নাম আছে।

regex ফ্লেভার ও ভাষা-ভিত্তিক পার্থক্য

মূল টোকেন সেট — ক্যারেক্টার ক্লাস, কোয়ান্টিফায়ার, অ্যাংকর, গ্রুপ — ভাষাভেদে মোটামুটি সামঞ্জস্যপূর্ণ, কিন্তু প্রান্তে গিয়ে অর্থপূর্ণ পার্থক্য জমতে থাকে। JavaScript-এ ES2018-এর আগ পর্যন্ত লুকবিহাইন্ড সমর্থন ছিল না, ফলে পুরনো polyfill কোড প্রায়ই এর বিকল্প কৌশল ব্যবহার করে; u ফ্ল্যাগ সঠিক Unicode code-point ম্যাচিং চালু করে (emoji-এর মতো astral-plane ক্যারেক্টারের জন্য . ঠিক করে), s (dotAll) ফ্ল্যাগ .-কে newline ম্যাচ করতে দেয়, আর (?<name>…) দিয়ে named গ্রুপও ES2018-এ এসেছে। JavaScript-এ কোনো বিল্ট-ইন compiled-pattern অবজেক্ট নেই: RegExp ইনস্ট্যান্স নির্মাণের সময় কম্পাইল হয়, তাই কোনো loop-এর ভেতরে একই literal তৈরি করলে প্রতিটি iteration-এ তা আবার কম্পাইল হয় — এটি একটি সাধারণ পারফরম্যান্স ভুল। Python-এর re মডিউল PCRE সিনট্যাক্স ঘনিষ্ঠভাবে অনুসরণ করে, কিন্তু named গ্রুপের জন্য (?P<name>…), named backreference-এর জন্য (?P=name), এবং re.VERBOSE ফ্ল্যাগ (re.X) ব্যবহার করে যা প্যাটার্ন থেকে এস্কেপবিহীন whitespace সরিয়ে দেয় এবং inline # কমেন্ট অনুমোদন করে — জটিল প্যাটার্ন ডকুমেন্ট করতে অমূল্য। Python ব্যাকস্ল্যাশ দেখার আগেই তা ব্যাখ্যা করা এড়াতে সবসময় প্যাটার্নটি raw string হিসেবে (r"\d+") পাস করুন।

Java-র java.util.regex প্যাকেজে string literal-এ প্রতিটি ব্যাকস্ল্যাশ দ্বিগুণ করা দরকার, কারণ \ হলো Java-র string escape ক্যারেক্টার: \d+ regex-টি সোর্স কোডে "\\d+" হিসেবে লিখতে হয়। ফ্ল্যাগ প্রয়োগ হয় হয় constructor constant দিয়ে (Pattern.CASE_INSENSITIVE, Pattern.DOTALL) অথবা প্যাটার্নের ভেতরে inline (?i) হিসেবে। Pattern.compile() দিয়ে আগে থেকে কম্পাইল করা প্রোডাকশন কোডের জন্য গুরুত্বপূর্ণ, কারণ JVM স্বয়ংক্রিয়ভাবে প্যাটার্ন cache করে না। .NET সবচেয়ে ফিচার-সমৃদ্ধ বিল্ট-ইন ফ্লেভার দেয়: এটি (?>…) দিয়ে atomic গ্রুপ, possessive কোয়ান্টিফায়ার সমর্থন করে, এবং অনন্যভাবে balancing group সমর্থন করে — একটি সিনট্যাক্স এক্সটেনশন ((?<open-close>)) যা nesting গভীরতা ট্র্যাক করতে পারে, ফলে একটিমাত্র .NET regex balanced বন্ধনী ম্যাচ করতে পারে, যা regular language-এর ক্ষমতার কঠোরভাবে বাইরে। Go-র regexp প্যাকেজ নকশা অনুসারে RE2 ইঞ্জিন ব্যবহার করে: backreference ও লুকঅ্যাহেড compile time-এ প্রত্যাখ্যাত হয়, আর Unicode ক্যাটাগরি \p{L} (যেকোনো Unicode অক্ষর) দিয়ে পাওয়া যায়। এর বিনিময়ে মেলে নিরাপত্তা: Go regex O(n)-এর নিশ্চয়তা দেয় এবং একে catastrophic backtracking-এ বাধ্য করা যায় না।

POSIX EREgrep -E, awk এবং বহু Unix কমান্ড-লাইন টুল যে ফ্লেভার ব্যবহার করে — তাতে \d, \w\s shorthand ক্লাসগুলো একেবারেই নেই; বদলে আপনাকে [0-9][a-zA-Z0-9_] লিখতে হয়। ERE-তে কোনো লুকঅ্যাহেড নেই, non-capturing গ্রুপ নেই, backreference নেই (BRE \1 যোগ করে কিন্তু ভিন্ন এস্কেপিং নিয়মে), আর | দিয়ে অল্টারনেশনে এস্কেপ লাগে না। কোনো JavaScript বা Python প্যাটার্নকে শেল স্ক্রিপ্টে পোর্ট করতে গেলে প্রায়ই দেখা যায় অর্ধেক টোকেন নীরবে ভিন্ন কিছু বোঝায় — কিংবা কেবল অসমর্থিত। এই পেজের ফ্লেভার টেবিল সবচেয়ে প্রভাবশালী পার্থক্যগুলো ধরে রাখে, যাতে আপনি চমক ছাড়াই প্যাটার্ন অনুবাদ করতে পারেন।

রেগুলার এক্সপ্রেশনের সংক্ষিপ্ত ইতিহাস

রেগুলার এক্সপ্রেশনের উৎস formal language theory-তে। ১৯৫১ সালে গণিতবিদ Stephen Kleene regular sets নিয়ে তাঁর কাজ প্রকাশ করেন — এমন এক শ্রেণির ভাষা যা একটি finite-state machine চিনতে পারে — এবং সেগুলো বর্ণনায় তিনি যে বীজগাণিতিক নোটেশন ব্যবহার করেন তা-ই আজ আমরা রেগুলার এক্সপ্রেশন বলি। Kleene-র উপপাদ্য regular language ও finite automata-র মধ্যে সমতুল্যতা প্রতিষ্ঠা করে, যা কম্পিউটার বিজ্ঞানকে তার সবচেয়ে টেকসই তাত্ত্বিক স্তম্ভগুলোর একটি দেয়।

তত্ত্বটি ১৯৬৮ সালে একটি ব্যবহারিক টুলে রূপ নেয়, যখন Ken Thompson Bell Labs-এ Unix লাইন এডিটর ed-এ এবং পরে সার্চ ইউটিলিটি grep-এ একটি regex ইঞ্জিন বসান। Thompson-এর ইঞ্জিন একটি প্যাটার্নকে সরাসরি একটি non-deterministic finite automaton (NFA)-তে কম্পাইল করত, যা linear time-এ সিমুলেট করা যেত — Kleene-র গণিতের একটি পরিচ্ছন্ন প্রকৌশলগত অনুবাদ। grep শব্দটি নিজেই globally search a regular expression and print-এর সংক্ষিপ্ত রূপ, এবং টুলটি প্রতিটি Unix সিস্টেমের সাথে এসেছিল, যা regex-কে বিশ্বজুড়ে প্রোগ্রামারদের হাতে তুলে দেয়।

Unix ইকোসিস্টেম পরে POSIX স্ট্যান্ডার্ড তৈরি করে, যা দুটি ফ্লেভার নির্দিষ্ট করে: Basic Regular Expressions (BRE, grepsed-এ ডিফল্টভাবে ব্যবহৃত) এবং Extended Regular Expressions (ERE, grep -E বা awk দিয়ে চালু)। POSIX ERE এস্কেপবিহীন +, ?| অপারেটর যোগ করে কিন্তু ইচ্ছাকৃতভাবে লুকঅ্যাহেড ও backreference বাদ দেয়। নির্ধারক সম্প্রসারণটি আসে ১৯৮০-এর দশকে Perl-এর হাত ধরে: Perl-এর regex উপভাষা non-greedy কোয়ান্টিফায়ার, লুকঅ্যাহেড, লুকবিহাইন্ড, named গ্রুপ এবং আরও বহু ফিচার যোগ করে। ১৯৯৭ সালে Philip Hazel যখন এই উপভাষাকে একটি স্বতন্ত্র C লাইব্রেরি হিসেবে PCRE (Perl Compatible Regular Expressions) নামে বের করে আনেন, তখন সেই ফিচারগুলো পোর্টেবল হয়ে ওঠে — আর আজ বেশিরভাগ ডেভেলপার “regex” বলতে যা বোঝান তা মূলত PCRE সিনট্যাক্সই।

Catastrophic backtracking ও ReDoS আক্রমণ

সব regex প্যাটার্নই untrusted ইনপুটে চালানোর জন্য সমান নিরাপদ নয়। একটি ReDoS আক্রমণ (Regular Expression Denial of Service) সেই উপায়টির অপব্যবহার করে যেভাবে backtracking NFA-ভিত্তিক ইঞ্জিন প্যাটার্নের বিকল্পগুলো অনুসন্ধান করে। কোনো প্যাটার্নে nested কোয়ান্টিফায়ার থাকলে — ক্লাসিক উদাহরণ (a+)+ — ইঞ্জিন কোনো ম্যাচ নেই সিদ্ধান্তে আসার আগে একটি স্ট্রিং ম্যাচ করার সূচকীয়ভাবে বহু ভিন্ন উপায় চেষ্টা করতে পারে। "aaaaaaaaaaaaaab"-এর মতো একটি সাজানো ইনপুটে (a+)+b প্যাটার্নটি ২০টি পুনরাবৃত্ত ক্যারেক্টারের জন্য দশ লক্ষেরও বেশি backtracking চেষ্টা ঘটায়; ইনপুটের দৈর্ঘ্য দ্বিগুণ করলে ধাপের সংখ্যা মোটামুটি বর্গ হয়ে যায়, অর্থাৎ যথেষ্ট দীর্ঘ একটি স্ট্রিং একটিমাত্র regex মূল্যায়নে একটি সার্ভার থ্রেডকে সেকেন্ড বা মিনিটের জন্য থমকে দিতে পারে।

বাস্তব ঘটনা প্রমাণ করে এটি নিছক তাত্ত্বিক নয়। ২০১৬ সালের জুলাইয়ে Stack Overflow প্রায় ৩৪ মিনিট ধরে সাইট-জুড়ে বিকল হয়ে পড়ে, কারণ দীর্ঘ স্পেসের একটি স্ট্রিং-সমেত একটি বিদ্বেষপূর্ণ মন্তব্য Markdown পার্সারের regex-এ একটি ReDoS দুর্বলতা ট্রিগার করেছিল। Cloudflare ২০১৯ সালে একই ধরনের একটি প্রোডাকশন ঘটনা নথিভুক্ত করে। যেসব দুর্বল প্যাটার্ন কাঠামোর ওপর নজর রাখতে হবে সেগুলো হলো nested কোয়ান্টিফায়ার ((a*)*, (a+)+), overlapping অল্টারনেশন ((a|aa)+), এবং এমন যেকোনো সংমিশ্রণ যেখানে একটি গ্রুপের দুটি শাখাই একই ক্যারেক্টার একাধিক উপায়ে ম্যাচ করতে পারে।

প্রতিকারের উপায়গুলোর মধ্যে আছে মূল্যায়নের আগে একটি ইনপুট দৈর্ঘ্যের সীমা আরোপ করা, regex কলে একটি timeout সেট করা, এবং প্যাটার্নগুলো পুনর্লিখন করে possessive কোয়ান্টিফায়ার (PCRE-তে a++) বা atomic গ্রুপ ((?>a+)) ব্যবহার করা, যা কোনো সাব-এক্সপ্রেশন একবার ম্যাচ হয়ে গেলে backtracking তথ্য ফেলে দেয়। নিরাপত্তা-সংকটাপন্ন প্রেক্ষাপটে সবচেয়ে সম্পূর্ণ সমাধানটি হলো RE2 ইঞ্জিন — Google-এ তৈরি এবং Go, C++ ও Python-এর জন্য উপলব্ধ — যা প্যাটার্নকে একটি DFA-তে কম্পাইল করে যা ইনপুটের দৈর্ঘ্যে O(n) linear time-এর নিশ্চয়তা দেয়, ফলে catastrophic backtracking কাঠামোগতভাবেই অসম্ভব হয়ে পড়ে। বিনিময়ে RE2 ইচ্ছাকৃতভাবে backreference ও কিছু লুকঅ্যারাউন্ড অ্যাসারশন প্রত্যাখ্যান করে — ঠিক সেই ফিচারগুলোই যা সূচকীয় বিস্ফোরণ ঘটায়।

Frequently asked questions

উদাহরণসহ রেগুলার এক্সপ্রেশন কী?

একটি রেগুলার এক্সপ্রেশন (regex) হলো একটি সংক্ষিপ্ত প্যাটার্ন যা এক সেট স্ট্রিং বর্ণনা করে, টেক্সট সার্চ, ম্যাচ ও রিপ্লেস করতে ব্যবহৃত হয়। যেমন, \d{3}-\d{4} প্যাটার্নটি 555-1234-এর মতো একটি ফোন অংশ ম্যাচ করে, কারণ \d মানে ‘একটি সংখ্যা’ এবং {3} মানে ‘ঠিক তিনটি’। প্রায় প্রতিটি প্রোগ্রামিং ভাষা ও কোড এডিটরে regex find-and-replace, ফর্ম যাচাই এবং লগ পার্সিং চালায়। এই পেজের উপরে থাকা লাইভ টেস্টার আপনাকে যেকোনো প্যাটার্ন সঙ্গে সঙ্গে চেষ্টা করতে দেয়।

মৌলিক regex টোকেনগুলো কী কী?

মূল উপাদানগুলো হলো: . (newline ছাড়া যেকোনো ক্যারেক্টার), \d (একটি সংখ্যা), \w (একটি word ক্যারেক্টার — অক্ষর, সংখ্যা বা underscore), \s (whitespace), অ্যাংকর ^ (শুরু) ও $ (শেষ), এবং কোয়ান্টিফায়ার * (শূন্য বা তার বেশি), + (এক বা তার বেশি) ও ? (ঐচ্ছিক)। তাই \w+ একটি পুরো শব্দ ম্যাচ করে এবং \d+ 2024-এর মতো একটি পুরো সংখ্যা ম্যাচ করে। এদের একত্র করুন — ^\d+$ এমন একটি লাইন ম্যাচ করে যা কেবল সংখ্যায় গঠিত। এই চিট শিটের প্রতিটি টোকেনের সাথে একটি কপি-করার-যোগ্য উদাহরণ থাকে।

\d, \w এবং \s মানে কী?

\d যেকোনো সংখ্যা 0–9 ম্যাচ করে; \w একটি word ক্যারেক্টার (a–z, A–Z, 0–9 বা _) ম্যাচ করে; \s whitespace (স্পেস, ট্যাব বা newline) ম্যাচ করে। এদের বড় হাতের সংস্করণগুলো হলো বিপরীত: \D হলো non-digit, \W একটি non-word ক্যারেক্টার এবং \S একটি non-space। যেমন, ‘a5 b’ টেক্সটে \d ম্যাচ করে 5, \w ম্যাচ করে a, 5 ও b, এবং \s এদের মাঝের স্পেসটি ম্যাচ করে। এই তিনটি shorthand ক্লাস দৈনন্দিন regex প্যাটার্নের বিরাট অংশই কভার করে।

regex অ্যাংকর কী?

অ্যাংকর কোনো ক্যারেক্টার নয়, বরং একটি অবস্থান ম্যাচ করে। ^ স্ট্রিংয়ের শুরু ম্যাচ করে (বা m ফ্ল্যাগ দিয়ে প্রতিটি লাইন), $ শেষ ম্যাচ করে, \b একটি word boundary ম্যাচ করে এবং \B একটি non-boundary। যেমন, ^\d+$ কেবল সংখ্যায় গঠিত একটি স্ট্রিং ম্যাচ করে, আর \bcat\b ‘cat’ শব্দটি ম্যাচ করে কিন্তু ‘category’-র ভেতরের ‘cat’-কে নয়। অ্যাংকরকে প্রায়ই ভুল করে ক্যারেক্টার ম্যাচার ভাবা হয় — এগুলো টেক্সটে অবস্থান ম্যাচ করে, নির্দিষ্ট কোনো ক্যারেক্টার নয়।

regex-এ কোয়ান্টিফায়ার কী?

কোয়ান্টিফায়ার বলে দেয় আগের টোকেনটি কতবার পুনরাবৃত্তি হতে পারে: * হলো শূন্য বা তার বেশি, + এক বা তার বেশি, ? শূন্য বা এক (ঐচ্ছিক), {n} ঠিক n বার, {n,} n বা তার বেশি, এবং {n,m} n ও m-এর মধ্যে। এগুলো ডিফল্টভাবে greedy (যতটা সম্ভব ম্যাচ করে); lazy করতে একটি ? যোগ করুন। যেমন \d{1,3} ১ থেকে ৩টি সংখ্যা ম্যাচ করে, আর lazy .+? যতটা সম্ভব কম ম্যাচ করে। HTML ট্যাগ বা quoted স্ট্রিং ম্যাচ করার সময় lazy কোয়ান্টিফায়ার অপরিহার্য।

গ্রুপ ও ক্যাপচার গ্রুপ কী?

বন্ধনী (…) একটি capturing গ্রুপ তৈরি করে যা আপনি এক্সট্র্যাক্ট বা পুনরায় ব্যবহার করতে পারেন — (\d{4})-(\d{2}) ‘2024-06’-এর বছর group 1-এ এবং মাস group 2-এ ক্যাপচার করে। কেবল কোয়ান্টিফায়ারের জন্য গ্রুপ করা দরকার হলে (?:…) ব্যবহার করুন, আর (?<year>\d{4})-এর মতো named গ্রুপের জন্য (?<name>…)। \1-এর মতো একটি backreference group 1 যা ক্যাপচার করেছে তা আবার ম্যাচ করে, তাই (\w)\1 একটি দ্বিগুণ অক্ষর খুঁজে পায় — ‘hello’-র ‘ll’।

লুকঅ্যাহেড ও লুকবিহাইন্ড কী?

লুকঅ্যারাউন্ড নিশ্চিত করে যে কোনো টেক্সট আপনার ম্যাচের পাশে আছে (বা নেই), তা দখল না করেই। (?=…) একটি পজিটিভ লুকঅ্যাহেড, (?!…) একটি নেগেটিভ লুকঅ্যাহেড, (?<=…) একটি পজিটিভ লুকবিহাইন্ড এবং (?<!…) একটি নেগেটিভ লুকবিহাইন্ড। যেমন, \d+(?=px) ‘5px’-এর 5 ম্যাচ করে কিন্তু ‘px’ বাদ রাখে, আর (?<=\$)\d+ একটি আগের ডলার চিহ্ন দাবি করে ‘$9’-এর 9 ম্যাচ করে। লুকঅ্যারাউন্ড হলো সেই ফিচারগুলোর একটি যা আধুনিক regex ইঞ্জিনকে POSIX grep থেকে আলাদা করে।

regex ফ্ল্যাগ কী?

ফ্ল্যাগ পুরো প্যাটার্ন কীভাবে প্রয়োগ হবে তা বদলায়: g (global) প্রতিটি ম্যাচ খোঁজে, i একে case-insensitive করে, m (multiline) ^ ও $-কে প্রতিটি লাইন ম্যাচ করায়, s (dotall) .-কে newline ম্যাচ করতে দেয়, u পূর্ণ Unicode চালু করে এবং y (sticky) একটি নির্দিষ্ট অবস্থানে ম্যাচিং আটকে দেয়। JavaScript-এ আপনি এগুলো শেষ slash-এর পরে যোগ করেন, তাই /cat/gi টেক্সটে সর্বত্র ‘Cat’ ও ‘CAT’ ম্যাচ করে। এই পেজের টেস্টারে প্রতিটি ফ্ল্যাগের জন্য টগল বাটন আছে, যাতে আপনি এদের প্রভাব লাইভ দেখতে পারেন।

ইমেইল, ফোন নম্বর বা URL-এর জন্য কীভাবে regex লিখব?

ব্যবহারিক শুরুর প্যাটার্ন: ইমেইল — [\w.+-]+@[\w-]+\.[\w.-]+ ; URL — https?:\/\/[^\s]+ ; US ফোন — \(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}, যা 555-123-4567 এবং (555) 123 4567 দুটোই ম্যাচ করে। এগুলো বাস্তবসম্মত, সর্বব্যাপী নয় — অফিশিয়াল ইমেইল স্ট্যান্ডার্ড অনেক বেশি জটিল — তাই সবসময় উপরের লাইভ টেস্টার দিয়ে আপনার আসল ডেটায় এদের টেস্ট করুন, যেখানে Common patterns তালিকায় প্রতিটি মাত্র এক ক্লিকে পাওয়া যায়।

regex-এ বিশেষ ক্যারেক্টার কীভাবে এস্কেপ করব?

কোনো মেটাক্যারেক্টারকে literal হিসেবে ম্যাচ করতে তার আগে একটি ব্যাকস্ল্যাশ বসান। সাধারণত যেসব ক্যারেক্টারে এস্কেপ দরকার হয় সেগুলো হলো . ^ $ * + ? ( ) [ ] { } | \ এবং /। যেমন \. একটি literal ডট ম্যাচ করে এবং \$ একটি ডলার চিহ্ন ম্যাচ করে, তাই \d+\.\d{2} 19.99-এর মতো একটি দাম ম্যাচ করে। একটি ক্যারেক্টার ক্লাসের ভেতরে এদের বেশিরভাগ তাদের বিশেষ অর্থ হারায়, তাই [.]-ও এস্কেপ ছাড়াই একটি literal ডট ম্যাচ করে।

JavaScript, Python ও Java-র মধ্যে regex ফ্লেভার কি ভিন্ন হয়?

মূল সিনট্যাক্স অভিন্ন, কিন্তু খুঁটিনাটি আলাদা। JavaScript গ্রুপের নাম দেয় (?<name>…) দিয়ে, Python ব্যবহার করে (?P<name>…); Python raw string ব্যবহার করে যেমন r"\d+" এবং Java-র string literal-এ দ্বিগুণ ব্যাকস্ল্যাশ দরকার ("\\d+")। Dotall হলো JS-এ s ফ্ল্যাগ, Python-এ re.DOTALL এবং Java-তে Pattern.DOTALL। এই পেজের ফ্লেভার টেবিল Python, Java, PCRE ও grep-এর পার্থক্য সংক্ষেপে তুলে ধরে, যাতে আপনি আত্মবিশ্বাসের সাথে ভাষার মধ্যে একটি প্যাটার্ন পোর্ট করতে পারেন।

Python-এ রেগুলার এক্সপ্রেশন কী?

Python-এ রেগুলার এক্সপ্রেশন থাকে বিল্ট-ইন re মডিউলে। আপনি সাধারণত প্যাটার্নটি একটি raw string হিসেবে লেখেন এবং re.search, re.findall বা re.sub-এর মতো ফাংশন কল করেন — যেমন re.findall(r"\d+", "a1 b22") ফেরত দেয় ['1', '22']। Named গ্রুপ (?P<name>…) ব্যবহার করে এবং আপনি match.group('name') দিয়ে সেগুলো পড়েন। এই পেজের টোকেন রেফারেন্স সরাসরি Python regex-এ প্রযোজ্য; কেবল আশপাশের API এবং কয়েকটি ফ্ল্যাগের নাম JavaScript থেকে ভিন্ন।

কীভাবে একটি regex টেস্ট করব?

এই পেজের উপরের লাইভ টেস্টার ব্যবহার করুন: slash-এর মাঝে আপনার প্যাটার্ন টাইপ করুন, দরকারি ফ্ল্যাগগুলো টগল করুন এবং একটি টেস্ট স্ট্রিং পেস্ট করুন। ম্যাচগুলো রিয়েল টাইমে হাইলাইট হয়, প্রতিটি নম্বরযুক্ত ও নামযুক্ত ক্যাপচার গ্রুপ নিচে আলাদা করে দেখানো হয়, এবং একটি ভুল প্যাটার্ন নীরবে ব্যর্থ হওয়ার বদলে একটি inline এরর মেসেজ দেখায় — সবই আপনার ব্রাউজারে স্থানীয়ভাবে চলে, তাই আপনি যা পেস্ট করেন তা আপলোড হয় না। regex101.com ও regexr.com-এর মতো টুলও একইভাবে কাজ করে; এটি একই পেজে রেফারেন্স ও টেস্টার একসাথে করে।

regex101.com ও regexr.com-এর সাথে এর তুলনা কেমন?

regex101.com গভীর regex ডিবাগিংয়ের শিল্প-মান — এটি একাধিক ফ্লেভার সমর্থন করে (PCRE, Python, Java, .NET, Golang) এবং আপনার প্যাটার্নের প্রতিটি টোকেনের বিস্তারিত ব্যাখ্যা দেয়। regexr.com অবদান রাখা প্যাটার্নের একটি কমিউনিটি লাইব্রেরিসহ অনুরূপ অভিজ্ঞতা দেয়। দুটোই চমৎকার ডেডিকেটেড টুল। এই UtiloKit চিট শিট ভিন্ন: এটি একই পেজে একটি টোকেন রেফারেন্স টেবিলের সাথে একটি বেসিক লাইভ টেস্টার জুড়ে দেয়, যাতে আপনি ট্যাব না পাল্টেই সেকেন্ডের মধ্যে কিছু খুঁজে নিয়ে যাচাই করতে পারেন। জটিল প্রোডাকশন regex কাজের জন্য regex101.com-এর ফ্লেভার তুলনা ও বিস্তারিত ডিবাগার অপ্রতিদ্বন্দ্বী; ডেভেলপমেন্টের সময় দ্রুত খোঁজার জন্য এই রেফারেন্স পেজ দ্রুত লোড হয় এবং কোনো নেভিগেশন লাগে না।

একে রেগুলার এক্সপ্রেশন বলা হয় কেন?

নামটি এসেছে formal language theory থেকে। ১৯৫০-এর দশকে গণিতবিদ Stephen Kleene ‘regular sets’ বর্ণনা করেন — এমন ভাষা যা একটি সাধারণ finite-state machine চিনতে পারে — এবং তিনি সেগুলোর জন্য যে নোটেশন ব্যবহার করেন তা রেগুলার এক্সপ্রেশন নামে পরিচিত হয়। আধুনিক regex ইঞ্জিন backreference ও লুকঅ্যারাউন্ডের মতো ফিচার যোগ করে যা কঠোরভাবে ‘regular’ ভাষার সীমা ছাড়িয়ে যায়, কিন্তু ঐতিহাসিক নামটি টিকে গেছে।