背景
私が以前書いた記事でこの正規表現について勉強する為です。
まずuフラグについて理解する必要があるのでそちらを書きます。
u (unicode) フラグ
ES2015 に u (unicode) フラグが導入され、コードポイント単位で正規表現を扱えるようになった。
コードポイントとは Code Point
「文字」に対する「一意のID」のこと
"A" という文字には、 U+0041 というコードポイントが割り当てられる
console.log('A'.codePointAt(0).toString(16)) //41 console.log(`\\u{41}`) //'A'
Code Pointは\u{Code Pointの16進数の値}のようにエスケープシーケンスとして記述できる
以下の例のように、uフラグをつけることでUnicode文字を正規表現で扱えます。
const str = 'A'; /\\u{41}/.test(str); // false /\\u{41}/u.test(str); // true
RegExp Unicode Property Escapes \p{...}, \P{...}とvフラグ
RegExp Unicode Property Escapesとは Unicode character class escape: \p{...}, \P{...}
\p{…},\P{…} を使うには、uフラグをセットで使います。 Unicode文字Propertyにどんなものがわからなかったですが、こちら参考になりました。 Unicode Utilities: Character Properties
// "Emoji "というUnicode文字Propertyの正規表現を定義 const re = /^\\p{Emoji}$/u; // 1つのコードポイントからなる絵文字をマッチさせる re.test('⚽'); // '\\u26BD' // → true ✅ // 複数のコードポイントからなる絵文字をマッチさせる re.test('👨🏾⚕️'); // '\\u{1F468}\\u{1F3FE}\\u200D\\u2695\\uFE0F' // → false ❌
上の例では、👨🏾⚕️ の絵文字は複数のコードポイントから構成されている EmojiはUnicode文字Propertyであるため、正規表現はマッチしない Emoji
以下のようにvフラグを付けると、Unicode文字列Propertyを利用して、1文字より長い文字列にマッチすることができる
const re = /^\\p{RGI_Emoji}$/v; // 1つのコードポイントからなる絵文字をマッチさせる re.test('⚽'); // '\\u26BD' // → true ✅ // 複数のコードポイントからなる絵文字をマッチさせる re.test('👨🏾⚕️'); // '\\u{1F468}\\u{1F3FE}\\u200D\\u2695\\uFE0F' // → true ✅
vフラグは、以下のUnicode文字列プロパティのサポートを最初から有効にしている
- Basic_Emoji
- Emoji_Keycap_Sequence
- RGI_Emoji_Modifier_Sequence
- RGI_Emoji_Flag_Sequence
- RGI_Emoji_Tag_Sequence
- RGI_Emoji_ZWJ_Sequence
- RGI_Emoji
集合表記とUnicode文字プロパティ,Unicode文字列プロパティ
差集合 -- Unicode文字プロパティ
/\\p{Script_Extensions=Greek}/v.test('π'); // → true /[\\p{Script_Extensions=Greek}--π]/v.test('π'); // → false
Unicode文字列プロパティ
/\\p{RGI_Emoji_Tag_Sequence}/v.test('🏴'); // → true /[\\p{RGI_Emoji_Tag_Sequence}--\\q{🏴}]/v.test('🏴'); // → false
積集合(共通部分) &&
const re = /[\\p{Script_Extensions=Greek}&&\\p{Letter}]/v; // U+03C0 ギリシャ小文字π re.test('π'); // → true // U+1018A ギリシャで0記号 re.test('𐆊'); // → false
和集合(合併)
const re = /^[\\p{Emoji_Keycap_Sequence}\\p{ASCII}\\q{🇧🇪|abc}xyz0-9]$/v; re.test('4️⃣'); // → true Emoji_Keycap_Sequence re.test('_'); // → true ASCII re.test('🇧🇪'); // → true re.test('abc'); // → true re.test('x'); // → true re.test('4'); // → true
大文字小文字を区別しないマッチングの改善
iフラグを使ってるので本来なら^\P,\pも同じ結果になるはずが以下のようになる Lowercase_Letterは小文字のUnicode文字プロパティ
const re1 = /\\p{Lowercase_Letter}/giu; const re2 = /[^\\P{Lowercase_Letter}]/giu; const string = 'aAbBcC4#'; string.replaceAll(re1, 'X'); // → 'XXXXXX4#' string.replaceAll(re2, 'X'); // → 'aAbBcC4#''
vフラグに変えると改善されて、同じ結果になる
const re2 = /[^\\P{Lowercase_Letter}]/giv; const string = 'aAbBcC4#'; string.replaceAll(re2, 'X'); // → 'XXXXXX4#'
参考
その他
Ecma InternationalのTC39は、JavaScript開発者、実装者、専門家などのグループで、JavaScriptの仕様をメンテナンスし発展させるためにコミュニティと協力しています