Flag، Lookahead و Lookbehind: کنترل دقیق‌تر رفتار تطابق

تا این‌جا الگوهای عبارت باقاعده به شکل ساده و بدون هیچ تنظیم اضافی نوشته شده‌اند. در این درس، سه ابزار پیشرفته‌تر بررسی می‌شود: Flagها که رفتار کلی یک الگو را تغییر می‌دهند، و Lookahead/Lookbehind که امکان بررسی شرطی متن اطراف یک الگو را فراهم می‌کنند، بدون آنکه آن بخش اطراف واقعاً جزو تطابق نهایی باشد.

Flagهای رایج عبارات باقاعده

Flag حرفی است که پس از اسلش دوم یک عبارت باقاعده نوشته می‌شود و رفتار کلی الگو را تغییر می‌دهد:

Flag معنی
g (global) یافتن تمام تطابق‌ها در رشته، نه فقط اولین مورد
i (ignore case) نادیده گرفتن تفاوت حروف بزرگ و کوچک
m (multiline) رفتار ^ و $ را به ابتدا و انتهای هر خط، نه کل رشته، تغییر می‌دهد
s (dotAll) اجازه می‌دهد نقطه (.) با خط جدید نیز مطابقت پیدا کند

تفاوت رفتار با و بدون Flag g

یکی از رایج‌ترین اشتباهات، فراموش‌کردن Flag g هنگام نیاز به یافتن تمام تطابق‌هاست:

تفاوت match با و بدون flag g
خروجی کنسول اینجا نمایش داده می‌شود...

نکته‌ی مهم این است که با Flag g، ساختار مقدار بازگشتی match کاملاً تغییر می‌کند: به‌جای شیئی با اطلاعات کامل درباره‌ی موقعیت و Capturing Groupها، فقط یک آرایه‌ی ساده از رشته‌های مطابق‌شده برگردانده می‌شود.

ترکیب چند Flag با هم

Flagها را می‌توان با هم ترکیب کرد؛ ترتیب نوشتن آن‌ها اهمیتی ندارد:

const pattern = /hello/gi;

console.log("Hello world, hello again".match(pattern));
// ["Hello", "hello"]

Lookahead: بررسی شرطی متن بعد از الگو

Lookahead امکان می‌دهد شرطی درباره‌ی متن بعد از یک الگو بررسی شود، بدون آنکه آن بخش جزو تطابق نهایی باشد. Lookahead مثبت با (?=...) و Lookahead منفی با (?!...) نوشته می‌شود:

// یافتن عددی که بلافاصله بعد از آن کلمه‌ی "تومان" آمده، بدون شامل شدن خود "تومان"
const pattern = /\d+(?=\s*تومان)/;

console.log("100 تومان".match(pattern)[0]); // "100"

// Lookahead منفی: عددی که بعد از آن "تومان" نیامده باشد
const notToman = /\d+(?!\s*تومان)/;
console.log("50 دلار".match(notToman)[0]); // "50"

Lookbehind: بررسی شرطی متن قبل از الگو

Lookbehind دقیقاً همان کار Lookahead را انجام می‌دهد، اما برای متن پیش از الگو. Lookbehind مثبت با (?<=...) و Lookbehind منفی با (?<!...) نوشته می‌شود:

// یافتن عددی که بلافاصله قبل از آن علامت $ آمده، بدون شامل شدن خود $
const pattern = /(?<=\$)\d+/;

console.log("قیمت: $250".match(pattern)[0]); // "250"

کاربرد عملی ترکیبی: اعتبارسنجی رمز عبور قوی

Lookahead به‌ویژه در اعتبارسنجی رمز عبور کاربرد فراوانی دارد، جایی که باید چند شرط مستقل هم‌زمان بررسی شوند:

// حداقل یک حرف بزرگ، یک رقم، و حداقل ۸ کاراکتر
const strongPassword = /^(?=.*[A-Z])(?=.*\d).{8,}$/;

console.log(strongPassword.test("Password1")); // true
console.log(strongPassword.test("password"));  // false؛ بدون حرف بزرگ و رقم

در این الگو، هر Lookahead به‌طور مستقل فقط بررسی می‌کند که شرط موردنظر در جایی از رشته برقرار باشد، بدون آنکه موقعیت خواندن رشته را تغییر دهد؛ به همین دلیل چند Lookahead می‌توانند پشت سر هم، بدون تداخل، نوشته شوند.

جدول مقایسه‌ی Lookahead و Lookbehind

نوع نحو بررسی می‌کند
Lookahead مثبت (?=...) متن بعدی باید با الگو مطابقت داشته باشد
Lookahead منفی (?!...) متن بعدی نباید با الگو مطابقت داشته باشد
Lookbehind مثبت (?<=...) متن قبلی باید با الگو مطابقت داشته باشد
Lookbehind منفی (?<!...) متن قبلی نباید با الگو مطابقت داشته باشد

نکات کلیدی

  • Flagهایی مثل g، i، m و s رفتار کلی یک عبارت باقاعده را بدون تغییر خود الگو، تغییر می‌دهند.
  • با Flag g، متد match آرایه‌ای ساده از تمام تطابق‌ها برمی‌گرداند، نه اطلاعات کامل درباره‌ی اولین تطابق.
  • Lookahead و Lookbehind شرطی درباره‌ی متن اطراف یک الگو بررسی می‌کنند، بدون آنکه آن بخش جزو تطابق نهایی باشد.
  • ترکیب چند Lookahead مستقل، ابزار رایجی برای اعتبارسنجی شرایط متعدد و هم‌زمان مثل قدرت رمز عبور است.

جمع‌بندی

Flagها امکان تنظیم رفتار کلی یک عبارت باقاعده—مثل حساسیت به حروف بزرگ و کوچک یا یافتن همه‌ی تطابق‌ها—را فراهم می‌کنند، در حالی که Lookahead و Lookbehind ابزارهایی دقیق‌تر برای بررسی شرطی متن اطراف یک الگو، بدون تأثیر بر خود تطابق، ارائه می‌دهند. ترکیب این ابزارها با آنچه در دو درس قبل درباره‌ی Character Class و Group آموختید، امکان ساخت الگوهای بسیار دقیق و کاربردی را فراهم می‌کند.