অনেক সময় আমাদের এমন প্যাটার্ন খুঁজা লাগে যা অন্য প্যাটার্নের উপর নির্ভর করে।
এজন্য রেগুলার এক্সপ্রেশনে একটি বিশেষ সিনট্যাক্স আছে "লুকঅ্যাহেড" এবং "লুকবিহাইন্ড", এদের একত্রে বলা হয় "লুকঅ্যারাউন্ড"।
চলুন একটি ব্যবহারিক উদাহরণ দেখি, subject:1 turkey costs 30€
এ স্ট্রিং হতে আমরা দাম খুঁজে বের করব। প্যাটার্নটি হবে প্রথমে একটি subject:€
চিহ্ন তারপর একটি সংখ্যা।
সিনট্যাক্সটি হবে: pattern:X(?=Y)
, এটি দ্বারা বুঝায় এর সাথে মিলবে pattern:X
, কেবলমাত্র এটি যদি pattern:Y
দ্বারা শুরু হয়। pattern:X
এবং pattern:Y
এর পরিবর্তে যেকোন প্যাটার্ন হতে পারে।
subject:€
পর একটি পূর্ণ সংখ্যা হবে, সুতরাং রেগুলার এক্সপ্রেশনটি হবে pattern:\d+(?=€)
:
let str = "1 turkey costs 30€";
alert( str.match(/\d+(?=€)/) ); // 30, 1 এর সাথে মিল হবে না কেননা এর পূর্বে € নাই
লক্ষ্য করুন: লুকঅ্যাহেড হল একটি যাচাই পদ্ধতি, প্যারেন্টেসিসের কন্টেন্ট pattern:(?=...)
রেজাল্টের মধ্যে আসবে না অর্থাৎ রেজাল্ট হবে match:30
।
চলুন pattern:X(?=Y)
কিভাবে কাজ করছে তা বোঝার চেষ্টা করি, রেগুলার এক্সপ্রেশন ইঞ্জিন প্রথমে খুঁজবে pattern:X
এবং এরপর খুঁজবে pattern:Y
আছে কিনা। যদি এটি না মেলে, তাহলে ঐ মিলগুলো বাদ দিবে, এবং অনুসন্ধান চালিয়ে যাবে।
আমরা আরো জটিল অনুসন্ধানও চালাতে পারি, যেমন pattern:X(?=Y)(?=Z)
দ্বারা বুঝায়:
১. প্রথমে pattern:X
খুঁজবে।
২. পরবর্তী অনুসন্ধান চালাবে যদি pattern:X
এরপর pattern:Y
থাকে(অন্যথায় বাদ যাবে)।
৩. পরবর্তী অনুসন্ধান চালাবে যদি pattern:X
এরপর pattern:Z
থাকে(অন্যথায় বাদ যাবে)।
৪. যদি উভয়ই অনুসন্ধান মিলে, তাহলে pattern:X
রেজাল্ট দেখাবে।
অন্য কথায় বলা যায়, আমরা pattern:X
কে এমনভাবে খুঁজছি যার পরে pattern:Y
এবং pattern:Z
থাকবে।
এটি অবশ্যই সম্ভব হবে যদি pattern:Y
এবং pattern:Z
পরস্পর সাংঘর্ষিক না হয়।
যেমন, pattern:\d+(?=\s)(?=.*30)
দ্বারা বুঝায় pattern:\d+
এরপর একটি স্পেস থাকবে, এবং তারপর যেকোন অবস্থানে 30
থাকবে:
let str = "1 turkey costs 30€";
alert( str.match(/\d+(?=\s)(?=.*30)/) ); // 1
এক্ষেত্রে আমাদের প্রাপ্ত ফলাফলটি হবে 1
।
চলুন আমরা দামের বদলে পরিমাণ খুঁজে বের করি। সুতরাং সংখ্যাটি হবে pattern:\d+
যার পরে subject:€
থাকবে না।
এজন্য আমরা, নেগেটিভ লুকঅ্যাহেড এর সাহায্য নিতে পারি।
সিনট্যাক্সটি হবে: pattern:X(?!Y)
, এটি দ্বারা বুঝায় "pattern:X
কে খুঁজবে, কেবলমাত্র এরপর যদি pattern:Y
না থাকে"।
let str = "2 turkeys cost 60€";
alert( str.match(/\d+(?!€)/) ); // 2 (দামকে বাদ দেয়া হয়েছে)
লুকঅ্যাহেড একটি শর্ত আরোপ করে "পরবর্তী অবস্থান"।
লুকবিহাইন্ড ও অনুরূপ, কিন্তু এটি পূর্বের অবস্থান খুঁজে। অর্থাৎ এটি মিলবে কেবল প্যাটার্নের পূর্বের কোন একটি প্যাটার্নের সাথে মিললে।
সিনট্যাক্সটি হবে:
- পজেটিভ লুকবিহাইন্ড:
pattern:(?<=Y)X
,pattern:X
মিলবে, কেবল এরপূর্বে যদিpattern:Y
থাকে। - নেগেটিভ লুকবিহাইন্ড:
pattern:(?<!Y)X
,pattern:X
মিলবে, কেবল এরপূর্বে যদিpattern:Y
না থাকে।
যেমন, চলুন আমরা দামটিকে US ডলার চিহ্ন দ্বারা প্রকাশ করি। ডলার চিহ্ন সাধারণত সংখ্যার পূর্বে থাকে, সুতরাং $30
এটি খুঁজতে আমাদের প্যাটার্নটি হবে pattern:(?<=\$)\d+
-- দামের পূর্বে একটি subject:$
চিহ্ন:
let str = "1 turkey costs $30";
// রেজাল্টে ডলার চিহ্নটি আসবে না \$
alert( str.match(/(?<=\$)\d+/) ); // 30 (পরিমাণটি বাদ যাবে)
এবং আমাদের যদি পরিমাণটি লাগে, অর্থাৎ আর পূর্বে subject:$
থাকবে না, এজন্য আমরা নেগেটিভ লুকবিহাইন্ড ব্যবহার করতে পারব pattern:(?<!\$)\d+
:
let str = "2 turkeys cost $60";
alert( str.match(/(?<!\$)\d+/) ); // 2 (দাম বাদ যাবে)
সাধারণত, লুকঅ্যারাউন্ড এর প্যারেন্টেসিস এর কন্টেন্টগুলো রেজাল্টে আসেনা।
যেমন এই প্যাটার্নে pattern:\d+(?=€)
, pattern:€
এই চিহ্নটি আমাদের মিলের অংশ হিসেবে দেখাবে না। এটিই স্বাভাবিক: কেননা আমরা এখানে একটি সংখ্যার pattern:\d+
খুঁজ করছি, যেখানে pattern:(?=€)
এটি দ্বারা শুধুমাত্র আমরা নিশ্চিত করছি সংখ্যাটি subject:€
এরপর আসবে।
কিন্তু কিছু ক্ষেত্রে আমাদের লুক অ্যারাউন্ডের এক্সপ্রেশনটিকেও ক্যাপচার করতে হতে পারে, অথবা এর একটি অংশও হতে পারে। এটিও সম্ভব। আমাদের শুধু অংশটিকে আরেকটি আলাদা প্যারেন্টেসিসের মধ্যে লিখা লাগবে।
নিচের উদাহরণে আমরা দামের পাশাপাশি কারেন্সী চিহ্নকেও pattern:(€|kr)
ক্যাপচার করব:
let str = "1 turkey costs 30€";
let regexp = /\d+(?=(€|kr))/; // অতিরিক্ত একটি প্যারেন্টেসিস €|kr
alert( str.match(regexp) ); // 30, €
লুকবিহাইন্ডের জন্য অনুরূপ:
let str = "1 turkey costs $30";
let regexp = /(?<=(\$|£))\d+/;
alert( str.match(regexp) ); // 30, $
"লুকঅ্যাহেড" এবং "লুকবিহাইন্ড" (একত্রে বলা হয় "লুকঅ্যারাউন্ড") ব্যবহার উপযোগী যদি কোন অংশ এর আগে বা পরের অংশের উপর নির্ভর করে।
সাধারণ রেগুলার এক্সপ্রেশনের মাধ্যমেই আমরা একই ব্যাপার করতে পারি। অর্থাৎ যা সবকিছুর সাথেই মিল খুঁজবে, তারপর লুপের মাধ্যমে অই কন্টেক্সট গুলো যাচাই বাচাইয়ের মাধ্যমে খুঁজতে পারি।
মনে রাখবেন, str.match
(pattern:g
ফ্ল্যাগছাড়া) এবং str.matchAll
(সর্বদাই) মিলগুলোকে index
অ্যারে আকারে রিটার্ন করে, সুতরাং আমরা জানি আমাদের কোন ইনডেক্সে কোন কন্টেক্সট নিয়ে যাচাই বাছাই করা লাগবে।
তবে লুকঅ্যারাউন্ড এর মাধ্যমে আমরা এটি আরো সহজে করতে পারি।
লুকঅ্যারাউন্ড এর টাইপস:
প্যাটার্ন | টাইপ | ম্যাচ |
---|---|---|
X(?=Y) |
পজেটিভ লুকঅ্যাহেড | pattern:X এর পরবর্তী প্যাটার্ন হবে pattern:Y |
X(?!Y) |
নেগেটিভ লুকঅ্যাহেড | pattern:X এর পরবর্তী প্যাটার্ন pattern:Y হবে না |
(?<=Y)X |
পজেটিভ লুকবিহাইন্ড | pattern:X এর পূর্ববর্তী প্যাটার্ন হবে pattern:Y |
(?<!Y)X |
নেগেটিভ লুকবিহাইন্ড | pattern:X এর পূর্ববর্তী প্যাটার্ন pattern:Y হবে না |