Unicode プロパティエスケープ

Unicode プロパティエスケープによって、正規表現において、その Unicode プロパティに基づいて文字を照合することができます。文字を、バイナリー(「論理値」)またはバイナリーではないいくつかのプロパティによって記述します。例えば、 Unicode プロパティエスケープは、絵文字、句読点、文字(特定の言語や文字体系からの文字も含む)などに一致するように使用することができます。

試してみましょう

メモ: Unicode プロパティエスケープを動作させるためには、正規表現は文字列を一連の Unicode コードポイントと見なすべきであることを示す u フラグ を使用する必要があります。 RegExp.prototype.unicode も参照してください。

メモ: Unicode プロパティには、一部の文字クラスよりも多くの文字を包含するものがありますが(\w がラテン文字 の a から z までしか一致しないなど)、後者のほうがブラウザー間での対応が進んでいます(2020 年 1 月現在)。

構文

// バイナリー値でないもの
\p{UnicodePropertyValue}
\p{UnicodePropertyName=UnicodePropertyValue}

// バイナリー値と非バイナリー値
\p{UnicodeBinaryPropertyName}

// 否定: \P は \p の否定
\P{UnicodePropertyValue}
\P{UnicodeBinaryPropertyName}

PropertyValueAliases.txt も参照してください。

UnicodeBinaryPropertyName

バイナリープロパティの名前。例えば、 ASCII, Alpha, Math, Diacritic, Emoji, Hex_Digit, Math, White_space, など。詳しくは Unicode Data PropList.txt を参照してください。

UnicodePropertyName

非バイナリープロパティの名前です。

UnicodePropertyValue

下記の「値」の節に掲載されているトークンの 1 つです。多くの値には、別名や短縮形があります(例えば General_Category プロパティの値 Decimal_NumberNd, digit, Decimal_Number と書くことができます)。ほとんどの値では、 UnicodePropertyName の部分と等号を省略することができます。 UnicodePropertyName を指定した場合、その値は指定されたプロパティの種類に対応するものでなければなりません。

メモ: 利用できるプロパティと値は膨大であるため、ここでは網羅的に記述することはせず、様々な例を提供することにします。

一般カテゴリー

一般カテゴリーは、Unicode 文字を分類するために使用され、より詳細なカテゴリーを定義するためにサブカテゴリーを利用することができます。Unicode プロパティエスケープでは、短い形式と長い形式の両方を使用することができます。

これらは、文字、数字、記号、句読点、空白などを照合するために使用することができます。一般的なカテゴリーのより詳細なリストについては、Unicode 仕様書を参照してください。

// この中のすべての文字を検索
const story = "It's the Cheshire Cat: now I shall have somebody to talk to.";

// 最も明示的な形式
story.match(/\p{General_Category=Letter}/gu);

// 一般カテゴリーでは、プロパティ名を使用することが必須ではありません。
story.match(/\p{Letter}/gu);

// 同等です(短い別名)。
story.match(/\p{L}/gu);

// これも同等です(短い別名を使用したすべてのサブカテゴリーの結合)。
story.match(/\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}/gu);

文字体系と文字体系拡張

言語によっては、その書法に別の文字体系を使用しているものもあります。例えば、英語とスペイン語はラテン文字を使用して書かれていますが、アラビア語とロシア語は他の文字(それぞれアラビア文字とキリル文字)を使用して書かれています。 Unicode の ScriptScript_Extensions プロパティは、正規表現が、主に使用される文字体系 (Script) または文字体系の集合 (Script_Extensions) に従って文字に一致するようにするものです。

例えば、 ALatin に、 εGreek に属します。

const mixedCharacters = "aεЛ";

// この文字体系の正規の「長い」名前を使用
mixedCharacters.match(/\p{Script=Latin}/u); // a

// Using a short alias for the script
mixedCharacters.match(/\p{Script=Greek}/u); // ε

// Script プロパティの短い名前 sc を使用
mixedCharacters.match(/\p{Sc=Cyrillic}/u); // Л

より詳細には、 Unicode 仕様書およびECMAScript 仕様書の文字体系 (Script) 一覧表.

ある文字が限られた文字体系で使用されている場合、 Script プロパティは「主要な」使用されている文字体系に対してのみ一致します。もし、「主要ではない」文字体系に基づいて文字を照合したい場合には、 Script_Extensions プロパティ(Scx と略します)を使用することができます。

// ٢ は、アラビア・インド語表記の数字の 2 であり、
// 主にアラビア文字体系で書かれるが、ターナ文字体系でも
// 使用することができます。

"٢".match(/\p{Script=Thaana}/u);
// ターナ文字体系は主要な文字体系ではないので null

"٢".match(/\p{Script_Extensions=Thaana}/u);
// ["٢", index: 0, input: "٢", groups: undefined]

Unicode プロパティエスケープと文字クラス

JavaScript の正規表現では、文字クラスで、特に \w\d を使用して文字や数字に一致させることも可能です。しかし、このような形式は ラテン 文字体系の文字にしか一致しません(言い換えれば、 a から zA から Z\w に、0 から 9\d に対応します)。この例に示すように、ラテン文字以外のテキストで作業するにはちょっと不便かもしれません。

Unicode プロパティエスケープのカテゴリーはより多くの文字を包含しており、 \p{Letter}\p{Number} はどのような文字体系に対しても扱うことができます。

// 範囲を使用して \w の制限を避けようとする

const nonEnglishText = "Приключения Алисы в Стране чудес";
const regexpBMPWord = /([\u0000-\u0019\u0021-\uFFFF])+/gu;
// BMP は U+0000 から U+FFFF だが、空白は U+0020

console.table(nonEnglishText.match(regexpBMPWord));

// Unicode プロパティエスケープを代わりに使用する
const regexpUPE = /\p{L}+/gu;
console.table(nonEnglishText.match(regexpUPE));

関連情報