۵ ژانویه ۲۰۲۳

الگو ها و پرچم ها (Patterns and flags)

عبارات باقاعده (Regular expressions) الگوهایی هستند که روشی قدرتمند برای جستجو و جایگزینی در متن ارائه می دهند.

در جاوااسکریپت، آنها از طریق شیء RegExp استفاده می شوند و همچنین به خوبی با متد های رشته ها ادغام می شوند.

عبارات باقاعده (Regular Expressions)

عبارت باقاعده (همچنین “regexp”، یا فقط “reg”) از یک الگو(pattern) و پرچم های(flags) اختیاری تشکیل می شوند.

دو روش وجود دارد که می توان از آنها برای ایجاد یک شیء عبارت باقاعده استفاده کرد.

سینتکس “طولانی”:

regexp = new RegExp("pattern(الگو)", "flags(پرچم)");

و سینتکس “کوتاه” نیز، استفاده از اسلش "/" می باشد.

regexp = /pattern/; // بدون پرچم
regexp = /pattern/gmi; // (به زودی گفته می‌شود) i، m، g با پرچم

اسلش های /.../ به جاوااسکریپت می گوید که ما در حال ایجاد یک عبارت باقاعده هستیم. آنها همان نقش کوتیشن(') را برای رشته ها بازی می کنند.

در هر دو مورد، regexp به یک نمونه از کلاس درون‌ساختRegExp تبدیل می‌ شود.

تفاوت اصلی بین این دو سینتکس این است که الگو با استفاده از اسلش‌های /.../، اجازه درج عبارات را نمی دهد (مانند حروف الفبای قالب(template literals) رشته با ${...}). آنها کاملا ایستا هستند.

اسلش ها زمانی استفاده می شوند که عبارت باقاعده را در زمان نوشتن کد بدانیم – و این رایج ترین حالت است. در حالی که new RegExp بیشتر زمانی استفاده می شود که ما “در حین انجام کار” نیاز به ایجاد یک regexp از یک رشته که به صورت پویا تولید شده داشته باشیم. برای مثال:

let tag = prompt("کدام تگ HTML را می خواهید پیدا کنید؟", "h2");

let regexp = new RegExp(`<${tag}>`); // خواهد بود /<h2>/ جواب داده شود درست مانند "h2" اگر در اعلان بالا

پرچم ها (Flags)

عبارات باقاعده ممکن است دارای پرچم هایی باشند که بر نحوه جستجو تأثیر بگذارد.

در جاوااسکریپت، تنها 6 مورد از آنها وجود دارد:

i
با این پرچم، جستجو به حروف کوچک و بزرگ حساس نیست: تفاوتی بین A و a نمی گذارد (به مثال زیر مراجعه کنید).
g
با این پرچم، جستجو برای همه موارد منطبق، بدون آن – فقط اولین موردی که هم خوانی دارد، برگردانده می شود.
m
حالت چند خطی (در فصل حالت چند خطی anchors ^ $، flag "m" پوشش داده شده است).
s
حالت dotall را فعال می‌ کند، که به یک نقطه .:pattern اجازه می‌ دهد تا با کاراکتر خط جدید n\ مطابقت داشته باشد (در فصل کلاس های کاراکتر (Character classes) پوشش داده شده است).
u
پشتیبانی کامل از یونیکد را فعال می کند. پرچم پردازش صحیح surrogate pair را امکان پذیر می کند. اطلاعات بیشتر در مورد آن در فصل یونیکد: پرچم "u" و کلاس {...}p\.
y
حالت Sticky: جستجو در موقعیت دقیق متن (در فصل Sticky flag "y", searching at position پوشش داده شده است)
رنگ ها

از اینجا به بعد رنگ بندی درون متن آموزش به این صورت است:

  • regexp – red (عبارت باقاعده خط قرمز دارد)
  • string (where we search) – blue (چیزی که جستجو می کنیم خط آبی دارد)
  • result – green (نتیجه خط سبز دارد)

جستجو: str.match

همانطور که قبلا ذکر شد، عبارات باقاعده با متدهای رشته ای ادغام می شوند.

متد str.match(regexp) همه تطابق های regexp را در رشته str پیدا می‌ کند.

و دارای 3 حالت کار است:

  1. اگر عبارت باقاعده دارای پرچم g باشد، آرایه‌ای از همه موارد مطابق با آن را بر می‌ گرداند:

    let str = "We will, we will rock you";
    
    alert( str.match(/we/gi) ); // We,we (آرایه ای از 2 رشته که مطابقت دارند)

    لطفاً توجه کنید که We و we نتیجه یکسانی می دهند، زیرا پرچم i باعث می‌ شود که عبارت باقاعده به حروف بزرگ و کوچک حساس نباشد.

  2. اگر چنین پرچمی وجود نداشته باشد، فقط اولین تطابق را در یک آرایه، با تطابق کامل در ایندکس 0 و برخی جزئیات اضافی در ویژگی ها بر می گرداند:

    let str = "We will, we will rock you";
    
    let result = str.match(/we/i); // بدون پرچم g
    
    alert( result[0] );     // We (اولین تطابق)
    alert( result.length ); // 1
    
    // Details:
    alert( result.index );  // 0 (موقعیت تطابق)
    alert( result.input );  // We will, we will rock you (رشته منبع)

    اگر بخشی از عبارت باقاعده در داخل پرانتز قرار بگیرد، ممکن است آرایه، ایندکس های دیگری در کنار ایندکس 0 نیز داشته باشد. ما آن را در فصل Capturing groups پوشش خواهیم داد.

  3. و در نهایت، اگر هیچ تطابقی وجود نداشته باشد، null بر می گرداند. (فرقی نمی‌ کند که پرچم g وجود داشته باشد یا خیر).

    این یک فرق ریز و بسیار مهم است. اگر هیچ تطابقی وجود نداشته باشد، یک آرایه خالی دریافت نمی‌ کنیم، بلکه null دریافت می‌ کنیم. فراموش کردن آن ممکن است منجر به خطاهایی شود، به عنوان مثال:

    let matches = "JavaScript".match(/HTML/); // = null
    
    if (!matches.length) { // Error: Cannot read property 'length' of null
      alert("خطا در خط بالایی");
    }

    اگر می‌ خواهیم نتیجه همواره به صورت یک آرایه باشد، می‌ توانیم آن را به این صورت بنویسیم:

    let matches = "JavaScript".match(/HTML/) || [];
    
    if (!matches.length) {
      alert("No matches"); // الان درست کار میکند
    }

جایگزین کردن: str.replace

روش str.replace(regexp، replacement) تطابق ‌هایی را که با استفاده از regexp در رشته str یافت می‌ شود را با replacement جایگزین می‌ کند (اگر پرچم g وجود داشته باشد همه منطبق هستند، در غیر این صورت، فقط اولین مورد تطابق دارد).

برای مثال:

// no flag g
alert( "We will, we will".replace(/we/i, "I") ); // I will, we will

// with flag g
alert( "We will, we will".replace(/we/ig, "I") ); // I will, I will

آرگومان دوم رشته replacement(جایگزین) است. می‌ توانیم از ترکیب کاراکترهای ویژه در آن برای درج قطعاتی از تطابق استفاده کنیم:

نماد عمل در رشته جایگزین
$& کل تطابق را درج می کند
$` قسمتی از رشته را قبل از تطابق وارد می کند
$' قسمتی از رشته را بعد از تطابق وارد می کند
$n اگرn یک عدد 1-2 رقمی باشد، محتویات پرانتزهای n را درج می کند، اطلاعات بیشتر در مورد آن در فصل Capturing groups
$<name> محتویات پرانتز را با name داده شده درج می کند، اطلاعات بیشتر در مورد آن در فصل Capturing groups
$$ کاراکتر “$” را درج می کند

مثالی برای $&:

alert( "I love HTML".replace(/HTML/, "$& and JavaScript") ); // I love HTML and JavaScript

تست کردن: regexp.test

متد regexp.test(str) حداقل یک تطابق را جستجو می‌ کند، در صورت یافتن true، در غیر این صورت false بر می گرداند.

let str = "I love JavaScript";
let regexp = /LOVE/i;

alert( regexp.test(str) ); // true

بعدا در این فصل، عبارات باقاعده بیشتری را یاد می گیریم. مثال‌ های بیشتری را مرور می‌ کنیم و همچنین با روش‌ های دیگری آشنا می‌ شویم.

اطلاعات کامل در مورد متد ها در مقاله Methods of RegExp and String آورده شده است.

خلاصه

  • یک عبارت باقاعده از یک الگو و پرچم‌ های اختیاری تشکیل شده است: g، i، m، u، s، y.
  • بدون پرچم و نمادهای خاص (که بعداً مطالعه خواهیم کرد)، جستجو توسط regexp مانند جستجوی زیر رشته(substring) است.
  • متد str.match(regexp) به دنبال تطابق است: اگر پرچم g وجود داشته باشد، همه آنها را بر می گرداند، در غیر این صورت، فقط اولین مورد را بر می گرداند.
  • متد str.replace(regexp، replacement) تطابق های یافت شده با استفاده از regexp را با replacement جایگزین می‌ کند: اگر پرچم g وجود داشته باشد به همه آنها این فرایند را اعمال می کند، در غیر این صورت فقط به اولین مورد اعمال می کند.
  • متد regexp.test(str) اگر حداقل یک مورد مطابقت داشته باشد، true بر می‌ گرداند، در غیر این صورت، false بر می‌ گرداند.
نقشه آموزش