۳۱ ژانویه ۲۰۲۳

یونیکد: پرچم "u" و کلاس {...}p\

جاوااسکریپت از رمزگذاری یونیکد برای رشته ها استفاده می کند. اکثر کاراکترها با 2 بایت کدگذاری می شوند، اما این امکان را برای نمایش حداکثر 65536 کاراکتر فراهم می کند.

این محدوده به اندازه کافی بزرگ نیست تا همه کاراکترهای ممکن را رمزگذاری کند، به همین دلیل است که برخی از کاراکترهای کمیاب با 4 بایت کدگذاری می شوند، به عنوان مثال مانند 𝒳 (X ریاضی) یا 😄 (لبخند)، برخی از هیروگلیف ها و غیره.

در اینجا مقادیر یونیکد برخی از کاراکترها آمده است:

کاراکتر یونیکد تعداد بایت یونیکد
a 0x0061 2
0x2248 2
𝒳 0x1d4b3 4
𝒴 0x1d4b4 4
😄 0x1f604 4

بنابراین کاراکتر هایی مانند a و 2 بایت را اشغال می کنند، در حالی که کدهای 𝒳، 𝒴 و 😄 طولانی تر هستند و 4 بایت دارند.

مدت ها پیش، زمانی که زبان جاوااسکریپت ایجاد شد، رمزگذاری یونیکد ساده تر بود: هیچ کاراکتر 4 بایتی وجود نداشت. بنابراین برخی از ویژگی های زبان را به اشتباه مدیریت می کردند.

به عنوان مثال، length فکر می کند که در اینجا دو کاراکتر وجود دارد:

alert('😄'.length); // 2
alert('𝒳'.length); // 2

…اما ما می توانیم ببینیم که فقط یک کاراکتر وجود دارد، درست است؟ نکته این است که length آن 4 بایت را به عنوان دو کاراکتر 2 بایتی در نظر می گیرد. این نادرست است، زیرا آنها باید فقط با هم در نظر گرفته شوند (به اصطلاح “surrogate pair”، می توانید در مورد آنها در مقاله رشته‌ها بخوانید).

به‌ طور پیش‌ فرض، عبارات باقاعده نیز “کاراکتر های طولانی” 4 بایتی را به عنوان یک جفت 2 بایتی در نظر می‌ گیرند. همانطور که در مورد رشته ها اتفاق می افتد، ممکن است به نتایج عجیب و غریب منجر شود. این را کمی بعد، در مقاله Sets and ranges [...] خواهیم دید.

برخلاف رشته‌ها، عبارات باقاعده دارای پرچم u هستند که چنین مشکلاتی را برطرف می‌ کند. با چنین پرچمی، یک regexp کاراکترهای 4 بایتی را به درستی مدیریت می کند. همچنین جستجوی ویژگی یونیکد در دسترس قرار می گیرد. در ادامه به آن خواهیم پرداخت.

ویژگی های یونیکد {…}p\

هر کاراکتر در یونیکد دارای ویژگی های زیادی است. آنها توصیف می کنند که کاراکتر به چه “رده ای” تعلق دارد و حاوی اطلاعات متفرقه در مورد آن است.

به عنوان مثال، اگر یک کاراکتر دارای ویژگی Letter باشد، به این معنی است که کاراکتر متعلق به الفبا (از هر زبان) است. ویژگی Number به این معنی است که آن کاراکتر یک رقم است: شاید عربی یا چینی و غیره.

می‌ توانیم کاراکترهایی را با یک ویژگی جستجو کنیم که به صورت {…}pattern:\p نوشته شده است. برای استفاده از {…}pattern:\p، یک عبارت باقاعده باید دارای پرچم u باشد.

برای مثال، {Letter}p\ یک حرف در هر زبانی را نشان می‌دهد. همچنین می‌ توانیم از p{L}\ استفاده کنیم، زیرا L نام مستعار Letter است. تقریباً برای هر ویژگی نام مستعار کوتاه تری وجود دارد.

در مثال زیر سه نوع حرف وجود دارد: انگلیسی، گرجی و کره ای.

let str = "A ბ ㄱ";

alert( str.match(/\p{L}/gu) ); // A,ბ,ㄱ
alert( str.match(/\p{L}/g) ); // null (کار نمی کند "u" بدون پرچم \p ،بدون انطباق)

در اینجا دسته بندی کاراکتر های اصلی و زیر شاخه های آنها آمده است:

  • حرف L:
    • حروف کوچک Ll
    • اصلاح کننده Lm,
    • عنوان Lt,
    • حروف بزرگ Lu,
    • سایر Lo.
  • عدد N:
    • رقم اعشاری Nd,
    • شماره نامه Nl,
    • سایر No.
  • نقطه گذاری P:
    • اتصال دهنده Pc,
    • خط تیره Pd,
    • نقل قول اولیه Pi,
    • نقل قول نهایی Pf,
    • باز Ps,
    • بسته Pe,
    • سایر Po.
  • علامت M (لهجه ها و غیره):
    • ترکیب فاصله Mc,
    • محصور کردن Me,
    • بدون فاصله Mn.
  • نماد S:
    • واحد پول Sc,
    • اصلاح کننده Sk,
    • ریاضی Sm,
    • سایر So.
  • جداکننده Z:
    • خط Zl,
    • پاراگراف Zp,
    • فاصله Zs.
  • سایر C:
    • کنترل Cc,
    • فرمت Cf,
    • اختصاص داده نشده Cn,
    • استفاده خصوصی Co,
    • جانشین Cs.

بنابراین، به عنوان مثال اگر به حروف کوچک نیاز داریم، می‌ توانیم \p{Ll}، علائم نگارشی: \p{P} و غیره را بنویسیم.

دسته های مشتق شده دیگری نیز وجود دارد، مانند:

  • Alphabetic (Alpha)، شامل حروف L، به اضافه اعداد حروف Nl (مثلاً Ⅻ – یک کاراکتر برای عدد رومی 12)، به‌علاوه برخی از نمادهای دیگر Other_Alphabetic (OAlpha).
  • Hex_Digit شامل اعداد هگزا دسیمال است. 0-9 a-f
  • …و غیره.

یونیکد از بسیاری از ویژگی های مختلف پشتیبانی می کند، لیست کامل آنها به فضای زیادی نیاز دارد، بنابراین در اینجا منابع آمده است:

مثال: اعداد هگزادسیمال

برای مثال، بیایید به دنبال اعداد هگزادسیمال بگردیم که به صورت xFF نوشته می‌ شوند، جایی که F یک رقم هگزاست (0…9 یا A…F).

یک رقم هگز را می توان به عنوان \p{Hex_Digit} نشان داد:

let regexp = /x\p{Hex_Digit}\p{Hex_Digit}/u;

alert("number: xAF".match(regexp)); // xAF

مثال: هیروگلیف چینی

بیایید دنبال هیروگلیف چینی بگردیم.

یک ویژگی یونیکد Script (یک سیستم نوشتاری) وجود دارد که ممکن است دارای مقدارهای روبرو باشد: Cyrillic، Greek، Arabic، Han (چینی) و غیره، فهرست کامل در اینجا آمده است.

برای جستجوی کاراکترها در یک سیستم نوشتاری معین، باید از <pattern:Script=<value استفاده کنیم، به عنوان مثال. برای حروف سیریلیک: \p{sc=Cyrillic}، برای هیروگلیف چینی: \p{sc=Han} و غیره:

let regexp = /\p{sc=Han}/gu; // هیروگلیف های چینی را برمی گرداند

let str = `Hello Привет 你好 123_456`;

alert( str.match(regexp) ); // 你,好

مثال: ارز

کاراکتر ‌هایی که یک ارز را نشان می‌ دهند، مانند $، ، ¥، دارای ویژگی یونیکد \p{Currency_Symbol} هستند، نام مستعار کوتاه: \p{Sc}.

بیایید از آن برای جستجوی قیمت‌ها در قالب “ارز و به دنبال آن یک رقم” استفاده کنیم:

let regexp = /\p{Sc}\d/gu;

let str = `Prices: $2, €1, ¥9`;

alert( str.match(regexp) ); // $2,€1,¥9

بعداً، در مقاله Quantifiers +, *, ? and {n} خواهیم دید که چگونه به دنبال اعدادی بگردیم که دارای ارقام زیادی هستند.

خلاصه

پرچم u پشتیبانی از یونیکد را در عبارات منظم فعال می کند.

یعنی دو چیز:

  1. کاراکترهای 4 بایتی به درستی مدیریت می شوند: به عنوان یک کاراکتر، نه دو کاراکتر 2 بایتی.
  2. از ویژگی های یونیکد می توان در جستجو استفاده کرد: {…}p\.

با ویژگی‌های یونیکد می‌توانیم به دنبال کلمات در زبان‌های معین، کاراکترهای خاص (نقل‌ ها، ارزها) و غیره بگردیم.

نقشه آموزش