こんばんは。初投稿です。正規表現についてまとめました。
使い方
「なんで使い方からやねん!」ってツッコミたくなりますよね。
正規表現は文字を探すためにあります。
/a/.test('I am neko.');// -> true
/a/.test('文字')
はa
を文字の中から見つけるという意味で、今回はamのaにヒットします。
ほかにも
/a/.exec('I am neko.');
/* ->
Object.assign(['a'], {
index: 2,
input: 'I am neko.',
groups: undefined
})
*/
でindex
を使って場所を調べたりできます。
作り方
/パターン/フラグ
new RegExp('パターン', 'フラグ')
パターンとフラグはあとでね。
/t/i.exec('This is test.');
new RegExp('t', 'i').exec('This is test.');
// 2つとも同じ
/* ->
Object.assign(['T'], {
index: 0,
input: 'This is test.',
groups: undefined
})
*/
パターン
パターンの書き方を教えます。覚えたらすごいね。
文字
ふつうの文字です。同じ文字があったらマッチします。
/a/.test('tasty');// a
/bc/.test('abcde');// bc
「もしくは~」です。[abc]
、[a-c]
、a|b|c
は全て同じです。
/[abc]/.test('symbol');// b
/[abc][abc]/.test('ban');// ba
/[a-e]/.test('suck');// c
// [a-e]は[abcde]と同じ意味
/ab|cd/.test('acd');// cd
/[0-9a-z]/.test('JACKP0T');// 0
/[9-0]/.test('JACKP0T');// エラー
// [z-a]、[9-0]などは順番が違う
「ではない~」です。[^]
と書きます。
/[^a-zA-Z]/.test('Testing:complete');// :
/[^abc]/.test('back');// k
「なにか」です。なにかがある。.
と書きます。
/b.d/.test('abcde');// bcd
/b..d/.test('abandon');// band
文字セットです。大文字になると反転します。
/\d/.test('I am number 011.');// 0
// [0-9]と同じ
/\D/.test('011: me');// :
// [^\d]と同じ
/\w/.test('アイスクリームyou scream');// y
// [a-zA-z0-9_]と同じ。アンダーバーも忘れずに。
/\W/.test('I screamユースクリーム');//
// ユじゃないよ~
/\s/.test('ねこちゃん わんちゃん');//
// スペースと区切り文字(全角、半角、タブ、改行など)に反応します。
/\S/.test(' \n\f\v\r\t
ここまで来たら真の\\S');// こ
// これからはスペースを打つ代わりに\sを使います。
繰り返し
めっちゃ簡単です。よかったね。
「n回繰り返す」です。文字{n}
と書きます。
文字をまとめるときは(?:)
と書きます。
/(?:にゃん){2}/.test('にゃんにゃん');// にゃんにゃん
/わん{3}/.test('わんんん');// わんんん
「n回以上繰り返す」は文字{n,}
と書きます。
/(?:のこ){1,}/.test('のこのこ');// のこのこ
// 「のこ」じゃないです
/(?:のこ){0,}/.test('none');//
// ''が結果です
「nからm回繰り返す」のは文字{n,m}
と書きます。
/(?:らく){1,3}/.test('らくらく');// らくらく
// 「らく」じゃないです
/(?:らく){0,1}/.test('らくらく');// らく
特別な繰り返し記号があります。
省略 | 繰り返し |
---|---|
文字* | 文字{0,} |
文字+ | 文字{1,} |
文字? | 文字{0,1} |
/ねこ*/.test('ねっこ');// ね
/ねこ+/.test('ねこ');// ねこ
/ねこ(?:ちゃん)?/.test('ねこ');// ねこ
位置(アサーション)
文字の位置を決めるためのものです。結果にはふくまれません。ここが少し難しいです。
最初の文字と最後の文字です。^
、$
と書きます。
/^[abc][def][ghi]$/.test('beg');// beg
文字じゃないもの(A-Za-z0-9_
)です。\b
と書きます。文字は\B
です。
/\bword/.test('a word');// word
// \bは文字じゃないのでスペースは含まない
/\Bward/.test('forward');// ward
// forのrは含まない
前置、後置です。(?<=)
と(?=)
/(?<=thank\s)you/.test('thank you');// you
/thank(?=\syou)/.test('thank you');// thank
ではないバージョンです。(?<!)
と(?!)
/(?<!thank\s)you/.test('here you are');// you
/thank(?!\syou)/.test('thanks');// thank
アサーションについて
解説パートをたまに挟んでみる。
アサーションで注意するべきなのは、それ自体は結果に含まれないということです。
では突然の問題
/a(?<=\s)b/.test('文字');// -> true
これが成立する文字はなんでしょうか?
正解はありません。なぜ無いのかというと、(?<=\s)が文字じゃないからです。ステップを踏んで考えてみましょう。
ステップ1: /(?<=\s)b/
は\s
が前にあるb
にマッチします。
つまり、/a(?<=\s)b/
は\s
がb
の前にあるab
にマッチします。\sb
とab
を同時に満たさなければならないのでありえません。
ちなみにアサーションは一番前と後ろに書く以外意味が無いです。
フラグ
どんな風に文字を探すか決めます。
i
iフラグは大文字と小文字を無視して探すことができます。
/thank\syou/i.test('Thank you');// Thank you
/U\sR/i.test('U r url');// U r
g
gフラグは挙動をガラリと変えます。だいたい「全てを探す」と思ってください。gフラグがないとエラーを出す関数も在ったりします。
let a = /a/,
b = /a/g;
a.test('apple');// -> true
console.log(a.lastIndex);// > 0
console.log(a.test('apple'));// > true
b.test('apple');// -> true
console.log(b.lastIndex);// > 1
b.test('apple');// > false
lastIndex
が使えるようになったり、lastIndex
から調べ始めたりします。
関数ごとに挙動がかなり変わるのであとでやります。
d
indicesというプロパティを生成します。
let result = /dea/d.exec('idea');
console.log(result.indices);
/* >
Object.assign([[1, 4]], {
groups: undefined
});
*/
m
^
と$
が文字列のはじめと終わりに加えて、行のはじめにもマッチするようになります。
/^I/m.test(`hi.
I ate it.`);// I
s
.
が改行にもマッチするようになります。
/an.apple/s.test(`an
apple`);// 'an\napple'
使い方
「いや二回目やん!」ってツッコミたくなりますよね。これでこの記事は終わりです!最後まで頑張っていきましょう!
前に紹介したtest
とexec
以外まだ関数はあるので見ていきましょう。
//.test()
マッチするものがあればtrue
なければfalse
を返します。
gフラグなし
const regex = /[^\w\s]/;
regex.test('Yes, I did.');// ,
regex.test('Yes, I did.');// ,
gフラグあり
const regex = /[^\w\s]/g;
regex.test('Yes, I did.');// ,
regex.test('Yes, I did.');// .
regex.test('Yes, I did.');// -> false
//.exec()
マッチしたときは配列、しないときはnullを返します。
gフラグなし
const regex = /\w+/;
regex.exec('an apple as an accessory');
/* ->
Object.assign(['an'], {
index: 0,
input: 'an apple as an accessory',
groups: undefined
});
*/
regex.exec('an apple as an accessory');// 同じ
gフラグあり
const regex = /\w+/g;
regex.exec('an apple as an accessory');// -> ['an']
regex.exec('an apple as an accessory');// -> ['apple']
''.match()
gフラグなし
gフラグなしの時のexec
と同じです。
const regex = /a/;
'apple'.match(regex);// -> regex.exec('apple')
gフラグあり
マッチした文字を配列で返します。
const regex = /a[a-z]*/g;
'apple banana'.match(regex);// -> [apple, anana]
'none'.match(regex);// -> null
''.matchAll()
gフラグなし
エラーです。_| ̄|○ ガックシщ(´□`)щ オーマイガーッ!!
gフラグあり
exec
の結果がつまったイテレーターを返します。
イテレーターの使い方
たまに聞くけどあんま分からないんだなーとか聞いたこともないんだなーっていう人のための使い方二選!
[...イテレーター];// -> [値1, 値2, …]
for (const 変数 of イテレーター) {
console.log(変数);
}
/* >
* 値1
* 値2
* ...
*/
ちなみに一度使ったイテレーターはもうゴミです。
const result = 'big bamboo'.matchAll(/b/g);
for (const val of result) {
console.log(val);
}
/***** 下のコードと同じ *****/
const regex = /b/g;
while (true) {
const result = regex.exec('big bamboo');
if (result === null) {
break;
} else {
console.log(result);
}
}
console.log([...'big bamboo'.matchAll(/b/g)]);
''.replace()
指向が変わって今度は文字を置き換えます。ここが山場です。ここを超えたらあとはウイニングランを楽しんでください。
gフラグなし
一番最初にマッチしたものを置き換えます。
'3匹の猫、2匹の犬'.replace(/\d/, '何');// -> 何匹の猫、2匹の犬
gフラグあり
すべて変換します。
'3匹の猫、2匹の犬'.replace(/\d/g, '何');// -> 何匹の猫、何匹の犬
共通
ここで終わりだと思ったら大間違いです。
記号 | 意味 |
---|---|
$$ | 「$」(エスケープ) |
$& | マッチした文字 |
$` | マッチした文字の前 |
$' | マッチした文字の後 |
'cocoa'.replace(/o/g, "$`");// -> 'ccccoca'
// c c(o) c coc(o) a
'cocoa'.replace(/o/g, "$'");// -> 'ccoacaa'
// c coa(o) c a(o) a
'11匹の猫'.replace(/\d+/g, "$&0");// -> '110匹の猫'
'10ドル'.replace(/ドル|dollar/g, "$$");// -> '10$'
まだ終わらないよ( `ー´)ノ
関数を入れるとまた違った動きをします。
'str'.replace(正規表現, (マッチした文字, インデックス, 文字全部) => 置き換える文字)
'97点'.replace(/\d/g, match => {
const kanjiNum = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
return kanjiNum[match];
});// -> '九七点'
'あああ0いいい0ううう'.replaceAll(/0/g, (match, index, str) => {
console.log(match, index, str);
});
/* 出力結果:
* '0', 3, 'あああ0いいい0ううう'
* '0', 7, 'あああ0いいい0ううう'
*/
おしまい!ウイニングラン楽しんでね★
''.replaceAll()
gフラグなし
エラーです。Allが付いてるのにgフラグ忘れるとかなめてんのか(; ・`д・´)
gフラグあり
gフラグありのときのreplace()
と同じです。
replace()との違い
正規表現を使う場合、違いはありません。文字を引数にするときに違いがでます。
'an apple'.replace('a', 'A');// -> 'An apple'
'an apple'.replaceAll('a', 'A');// -> 'An Apple'
''.search()
マッチした文字の最初のインデックス(場所)を返します。
const regexWg = /apple/g;
'I like apples'.search(regex);// -> 7
'I like apples'.search(regex);// -> 7
const regexWOg = /apple/;
'I like apples'.search(regex);// -> 7
'I like apples'.search(regex);// -> 7
gフラグありとなしで同じ結果を出します。gフラグは影響しません。
''.split()
区切って配列を作ります。
const regexWg = /,/g;
'月,火,水,木,金,土,日'.split(regexWg);// -> ['月', '火', '水', '木', '金', '土', '日']
'月,火,水,木,金,土,日'.split(regexWg);// -> ['月', '火', '水', '木', '金', '土', '日']
const regexWOg = /,/;
'月,火,水,木,金,土,日'.split(regexWOg);// -> ['月', '火', '水', '木', '金', '土', '日']
'月,火,水,木,金,土,日'.split(regexWOg);// -> ['月', '火', '水', '木', '金', '土', '日']
gフラグありとなしで同じ結果を出します。gフラグは影響しません。
その他
ここまで学んだらだいたいなんでもできます。おめでとうございます!でもまだあります\(^o^)/オワタ
余力があったら読んでね。
lastIndex
正規表現オブジェクトにはlastIndex
というプロパティが存在します。その値によって返す値が変わります。
test()
gフラグなし
影響しません。影響されません。
gフラグあり
lastIndex
から検索し始めます。
lastIndex
がヒットした文字の場所+1になります。
const regex = /an?/g;
console.log(regex.lastIndex);// > 0
// デフォルトは0
regex.test('an apple');
console.log(regex.lastIndex);// > 2
// anの最後の文字(n)のインデックス(0)プラス1(2)
regex.test('an apple');
console.log(regex.lastIndex);// > 4
// aのインデックス(3)プラス1(4)
regex.test('an apple');// -> false
console.log(regex.lastIndex);// > 0
// 一周すると0に戻る
regex.lastIndex = 2;
regex.test('a dog');// -> false
// dから探し始める
exec()
gフラグなし
影響しません。影響されません。
gフラグあり
仕組みはtest()
と同じです。
const regex = /an/g;
regex.exec('an apple and a banana');
console.log(regex.lastIndex);// > 2
regex.exec('an apple and a banana');
console.log(regex.lastIndex);// > 11
regex.exec('an apple and a banana');
console.log(regex.lastIndex);// > 18
regex.lastIndex = 1;
regex.exec('an apple and a banana');
console.log(regex.lastIndex);// > 11
matchAll()
影響しませんが影響されます。
const regex = /an/g;
regex.lastIndex = 4;
console.log([...'an apple and a banana'.matchAll(regex)]);
// (an)dとb(an)(an)aの3つ
最初は本当にバグだと思った。
貪欲モード
/(?:のこ)+/.test('のこのこ');// のこのこ
// 「のこ」じゃないです
これを「のこ」にする方法が存在するんです。
後ろに?
をつけると最低限でとめることができます。
/ねこ(?:にゃん)?/.test('ねこにゃんにゃん');// ねこにゃん
/ねこ(?:にゃん)*/.test('ねこにゃんにゃん');// ねこにゃんにゃん
/ねこ(?:にゃん){1,}/.test('ねこにゃんにゃん');// ねこにゃんにゃん
/ねこ(?:にゃん)??/.test('ねこにゃんにゃん');// ねこ
/ねこ(?:にゃん)*?/.test('ねこにゃんにゃん');// ねこ
/ねこ(?:にゃん){1,}?/.test('ねこにゃんにゃん');// ねこにゃん
バックリファレンス
量は多いですが質はそこそこです。さくさく行きましょ。
あとから使うためにグループで囲っておきます。
記号 | 説明 |
---|---|
() |
括弧内の文字列を、後で参照するために使用されます。 |
(?<group>) |
一致した文字列に名前(グループ)を付ます。 |
\1, \2... |
n番目の文字列を参照します。(例:\1 は最初の括弧内の文字列を参照) |
\k<group> |
(?<group>) で作成されたグループの文字列を参照します。 |
/([a-z])\1/.test('foo');// oo
// [a-z][a-z]とは違い「fo」にマッチしない
// 同じ小文字アルファベットが2つ並ぶとマッチ
/(?<letter>[a-z])\k<letter>/.test('foo');// oo
// 同じ原理
/(?<letter>[a-z])\1/.test('foo');// oo
// 名前付きキャプチャグループもグループとして数えられる
/(ab){2}(?<name>cd){2}/.test('ababcdcd');// ababcdcd
// (?:)と同じように使える
ここからマッチした後の話をしていきますね。
関数の振る舞いも変わってきます。
exec()
const result = /(a|an|the)\s(?<word>\w+)/.exec('there are an apple and a cat');
console.log(result[0]);// > an apple
console.log(result[1]);// > an
// 1つ目のグループの文字列
console.log(result[2]);// > apple
// 2つ目のグループの文字列
console.log(result.groups);// > { word: 'apple' }
// 「グループ名:文字列」のように保管されます
indices
プロパティも変わります。
const result = /(a|an|the)\s(?<word>\w+)/d.exec('there are an apple and a cat');
console.log(result.indices[0]);// > [10, 18]
console.log(result.indices[1]);// > [10, 12]
// 1つ目のグループのインデックス
console.log(result.indices[2]);// > [13, 18]
// 2つ目のグループのインデックス
console.log(result.indices.groups);// > { word: [13, 18] }
// 「グループ名:インデックス」のように保管されます
手抜きじゃないです(;'∀')
replace()
$n
と$<group>
が追加されます。
'an apple'.replace(/(a|an|the)\s(?<word>\w+)/g, '$1(冠詞) $<word>(名詞)');
// -> an(冠詞) apple(名詞)
関数にも新しく引数が追加されます。
''.replace(regex, (マッチした文字, 括弧1, 括弧2, ..., インデックス, 元の文字列, グループ) => 文字列);
'an apple'.replace(/(a|an|the)\s(?<word>\w+)/g, (match, n1, n2, index, string, group) => {
// ずれるため、n2は省略できない
let result = '';
if (n1 === 'the') {
result += 'その';
} else {
result += '一つの';
}
result += group.word;
console.log(match, n1, n2, index, string, group);
return result;
});// -> 一つのapple
/*
* match: an apple マッチした文字列
* n1: an グループ1
* n2: apple グループ2
* index: 0 インデックス
* string: an apple 全体の文字
* group: { word: 'apple' } グループ
*/
split()
グループされたら結果に含まれるようになります。
'{name}apple{price}500{description}sweet'.split(/{(.*?)}/);// あり
// -> ['', 'name', 'apple', 'price', '500', 'description', 'sweet']
'{name}apple{price}500{description}sweet'.split(/{.*?}/);// なし
// -> ['', 'apple', '500', 'sweet']
エスケープとuvフラグ
正真正銘の最後です。おおとりにして山場です。
これらは普通の文字列の時と同じです。
\f, \n, \r, \t, \v
\\
\0
\xhh, \uhhhh
同じだからって説明しなくて良い訳じゃ無いからね?
エスケープ | 意味 | 説明 |
---|---|---|
\f |
フォームフィード | 用紙を次のページへ進める。(現在はほとんど使用されない) |
\n |
改行 | カーソルを次の行の先頭へ移動。(改行) |
\r |
キャリッジリターン | カーソルを現在の行の先頭へ移動。(\n と組み合わせて使用される) |
\t |
水平タブ | タブスペースです。 |
\v |
垂直タブ | カーソルを次の垂直タブ位置へ移動。(現在はほとんど使用されない) |
\\ |
バックスラッシュ | バックスラッシュです。 |
\0 |
ヌル文字 | ヌル文字(U+0000)です。(次の文字が数字の場合オクタルエスケープ(非推奨)になります) |
\xhh |
16進数エスケープ | 2桁の16進数値(hh )に基づいて文字を表します。(U+0000~U+00FF) |
\uhhhh |
Unicodeエスケープ | 4桁のUnicodeコードポイント(hhhh )を使用して文字を表します。(U+0000~U+FFFF) |
ここから正規表現のみのエスケープです。
[\b]
// バックスペース文字です。文字列での\bと同じです。
// \bだけだとアサーションになります。
\ca, \cb, \cc, ... \cz
// aはU+0001, bはU+0002, ...
// 大文字でも同じです。
パターンで使われる文字はいろいろエスケープできます。
\{, \), \$, \?, ...
一覧
おさらいと共に、エスケープが必要な記号すべてを載せておきます。
記号 | 例 | おさらい |
---|---|---|
( と)
|
(abc) |
後で使う用にデータをとっておく |
[ と]
|
[a-z] |
a~zのどれかがあればマッチ |
{ と}
|
a{2,4} |
aa~aaaaにマッチ |
. |
a.b |
acbやalbにマッチ |
/ |
/abc/ |
abcにマッチ |
* |
ba* |
b, ba, baa, ...にマッチ |
+ |
ba+ |
ba, baa, baaa, ...にマッチ |
? |
ba? |
bかbaにマッチ |
$ |
abc$ |
文の最後のabcにマッチ |
^ |
^abc |
文の最初のabcにマッチ |
| |
abc|cba |
abcかcbaにマッチ |
- |
[a-z] |
[] の中だけで有効
|
ウォーミングアップは終わり。
uフラグ
新しいフラグです。
サロゲートペア
では問題です!
// あてはまる文字はなんだ?
/😀{2}/.test(文字);// -> true
// 制限時間: 10秒
正解は~?😀\ude00
でした~
サロゲートペアといって文字が二つに分割されてるんです。\u0000~\uffffまでの65536文字だとすべて表せなかったんですね~
console.log(😀[0]);// > '\uD83D'
console.log(😀[1]);// > '\uDE00'
// U+D83D・\uDE00自体は文字が設定されていないため�が表示されます
サロゲートペアの計算方法
unicode上のU+10000以上U+10FFFF以下の文字をUTF-16であらわす(計算)方法を載せておきます。
😀で実践してみます。😀はU+1f600です。
// 😀のコードポイント
const code = 0x1F600;
// codeと0x10000からの差分をとる
const offset = code - 0x10000;
console.log(offset.toString(2).padStart(20, '0'));
// > 00001111011000000000
// 上位・下位10ビットをとる
const high10Bits = offset >> 10;
console.log(high10Bits.toString(2).padStart(10, '0'));
// > 0000111101
const low10Bits = offset & 0b1111111111;
console.log(low10Bits.toString(2).padStart(10, '0'));
// > 1000000000
// 上位・下位サロゲートを足す
const highSurrogate = 0xD800 + high10Bits;
console.log(highSurrogate.toString(16));
// > d83d
const lowSurrogate = 0xDC00 + low10Bits;
console.log(lowSurrogate.toString(16));
// > de00
console.log('\ud83d\ude00');// > 😀
上位・下位サロゲートとは上位・下位サロゲート領域(サロゲート文字処理のために文字が割り当てられていないコードポイント範囲)に合わせるために足されるものです。
上位サロゲートはU+D800
~U+DBFF
で下位サロゲートはU+DC00
~U+DFFF
までです。
どちらも範囲は1024です。(0~1111111111)
これで1048576(2^20)文字使えるようになりました。
しかしこれをuフラグを使うことで回避できます。
/😀{2}/u.test('😀😀');// -> true
さらにuフラグを使うとunicodeエスケープを使うことができます。
/\u{1f600}/u.test('😀')// -> true
p{}、P{}
uフラグを使っているときはp{}
とP{}
が使えるようになります。P{}
は[^p{}]
(p{}の逆)です。
p{General Category}
UnicodeプロパティのGeneral category
を使って文字を指定することができます。
let regex;
regex = /\p{Lu}/u;
regex.test("A");// -> true
regex.test('Γ');// -> true
regex.test('a');// -> false
// Luは大文字にマッチ
regex = /\p{Ll}/u;
regex.test('a');// -> true
regex.test('γ');// -> true
regex.test('A');// -> false
// Llは小文字にマッチ
regex = /\p{Nd}/u;
regex.test("1");// -> true
regex.test("2");// -> true
// Ndは数字にマッチ
regex = /\p{P}/u;
regex.test(".");// -> true
regex.test(",");// -> true
// Pは記号にマッチ
regex = /\P{P}/u;
regex.test(".");// -> false
regex.test(",");// -> false
// 大文字は反転する
全種類
AIに作成させました。大体信用できるかな。
値 | 名前 | 説明 | 例 | 数 |
---|---|---|---|---|
L | Letter | アルファベット文字 | A,b,α,漢 | 約136,000 |
LC | Cased Letter | 大文字、小文字、タイトルケースの文字 | A,a,Dž | 約4,100 |
Lu | Uppercase Letter | 大文字のアルファベット | A,B,C | 約1,800 |
Ll | Lowercase Letter | 小文字のアルファベット | a,b,c | 約2,200 |
Lt | Titlecase Letter | タイトル用の特殊な文字 | Dž(例:"Džuro") | 約30 |
Lm | Modifier Letter | 他の文字を修飾する文字 | ˇ,ˋ | 約300 |
Lo | Other Letter | 他のサブカテゴリに属さない文字 | 漢,अ | 約130,000 |
M | Mark | ベース文字と組み合わせる記号 | ◌́,◌⃝ | 約2,000 |
Mn | Non-Spacing Mark | ベース文字に付属し、間隔を追加しないマーク | ◌́(アクセント) | 約1,700 |
Mc | Spacing Combining Mark | 結合後に間隔を追加するマーク | ◌ा(デーヴァナーガリー) | 約300 |
Me | Enclosing Mark | 他の文字を囲む記号 | ◌⃝(円形マーク) | 約20 |
N | Number | 数字 | 1,Ⅻ,⅔ | 約1,000 |
Nd | Decimal Digit | 通常の数字 | 0–9 | 約650 |
Nl | Letter Number | 文字の形をした数字 | Ⅻ,Ⅶ | 約170 |
No | Other Number | 分数や特殊な数字 | ⅔,㊾ | 約180 |
P | Punctuation | 文や文章を整理する記号 | .,?,“,” | 約1,000 |
Pc | Connector Punctuation | テキストセグメントを接続する記号 | _ | 約10 |
Pd | Dash Punctuation | ダッシュ | -,- | 約20 |
Ps | Open Punctuation | 開く括弧や引用符 | {,(,“ | 約50 |
Pe | Close Punctuation | 閉じる括弧や引用符 | },),” | 約50 |
Pi | Initial Quote | 開始用の引用符 | “ | 約10 |
Pf | Final Quote | 終了用の引用符 | ” | 約10 |
Po | Other Punctuation | その他の句読点 | !,&,/ | 約850 |
S | Symbol | さまざまな記号 | $,♠,☀ | 約8,000 |
Sm | Math Symbol | 数学的操作の記号 | +,÷,∑ | 約1,000 |
Sc | Currency Symbol | 通貨を表す記号 | $,¥,€ | 約70 |
Sk | Modifier Symbol | 他の記号の意味を修飾する記号 | ^,~ | 約120 |
So | Other Symbol | その他の特殊な記号 | ♠,☀,☎ | 約6,800 |
Z | Separator | 空白や改行を表す文字 | スペース,改行 | 約20 |
Zs | Space Separator | 通常の空白 | スペース,NBSP | 約17 |
Zl | Line Separator | テキスト行を分割する | 行セパレーター | 1 |
Zp | Paragraph Separator | テキスト段落を分割する | 段落セパレーター | 1 |
C | Other | 見えない文字やその他の文字 | Null,ZWNJ | 約65 |
Cc | Control | 制御用の文字 | NULL,ESC | 約65 |
Cf | Format | 書式コード | ZWNJ,ZWJ | 約160 |
Cs | Surrogate | サロゲートペアを構成する高位または低位の符号 | High Surrogate | 2048 |
Co | Private Use | カスタム用途の文字 | カスタムコードポイント | 約137,000 |
Cn | Not Assigned | 使用されていないコードポイント | 予約済みポイント | 可変 (残りの範囲) |
To get further information, please visit the link below.
https://en.wikipedia.org/wiki/Template:General_Category_(Unicode) (英語です)
\p{sc=}
\p{sc=言語}
と\p{scx=言語}
でその言語の文字を指定できます。
/\p{sc=Latin}/u.test('abc');// -> true
/\p{sc=Cyrillic}/u.test('л');// -> true
/\p{sc=Greek}/u.test('λ');// -> true
/\p{sc=Arabic}/u.test('ف');// -> true
/\p{sc=Devanagari}/u.test('ख');// -> true
/\p{sc=Katakana}/u.test('ニ');// -> true
/\p{sc=Hiragana}/u.test('ゃ');// -> true
/\p{sc=Han}/u.test('一');// -> true
// Hanは漢字や中国語にマッチ
/\p{sc=Hira}/u.test('。');// -> false
/\p{scx=Hira}/u.test('。');// -> true
// scxを使うとその言語っぽい物にもマッチ
/\p{Script=Hiragana}/u.test('。');// -> false
/\p{Script_Extensions=Hiragana}/u.test('。');// -> true
// scとscxは実はこれらの略
他の例
全種類じゃないです。もちろん追加されたりもします。AI生成です。
値 | 説明 | 例の文字 |
---|---|---|
Latin | 多くのヨーロッパ言語および他の多くの言語で使用されます。 | A,B,C,a,b,c |
Cyrillic | スラブ語および一部の非スラブ語で使用されます。 | Б,Д,Ж |
Arabic | アラビア語および一部の他の言語(例:ウルドゥー語)で使用されます。 | ا,ب,ت |
Devanagari | ヒンディー語、サンスクリット語、および他のインド言語で使用されます。 | अ,आ,इ |
Han | 中国語、日本語、韓国語の文字システムで使用されます。 | 日,本,語 |
Greek | ギリシャ語および数学記号で使用されます。 | Α,Β,Ω |
Hebrew | ヘブライ語および礼拝の文書で使用されます。 | א,ב,ג |
Thai | タイ語および関連する文字システムで使用されます。 | ก,ข,ค |
Armenian | アルメニア語で使用されます。 | Ա,Բ,Գ |
Bengali | ベンガル語、アッサム語、および関連する言語で使用されます。 | অ,আ,ই |
Tibetan | チベット語、ゾンカ語、および他のヒマラヤ言語で使用されます。 | ཀ,ཁ,ག |
Georgian | ジョージア語で使用されます。 | ა,ბ,გ |
Malayalam | インドのケーララ州で使われるマラヤーラム語で使用されます。 | അ,ആ,ഇ |
Sinhala | スリランカのシンハラ語で使用されます。 | අ,ආ,ඉ |
Cherokee | ネイティブアメリカン起源のチェロキー語で使用されます。 | Ꭰ,Ꭱ,Ꭲ |
Kannada | インドのカルナータカ州で使われるカンナダ語で使用されます。 | ಅ,ಆ,ಇ |
Runic | 古代のゲルマン語で使用された歴史的な文字システムです。 | ᚠ,ᚢ,ᚦ |
Katakana | 日本語の音節文字で、主に外来語に使用されます。 | カ,キ,ク |
Glagolitic | 中世のスラブ語で使用された歴史的な文字システムです。 | Ⰰ,Ⰱ,Ⰲ |
Thaana | モルディブのディベヒ語で使用されます。 | ހ,ށ,ނ |
Gujarati | インドのグジャラート語で使用されます。 | અ,આ,ઇ |
Gurmukhi | 主にインドで使用されるパンジャブ語で使用されます。 | ਅ,ਆ,ਇ |
Oriya | インドのオリヤ語で使用されます。 | ଅ,ଆ,ଇ |
Limbu | ネパールやインドで使用されるリンブ語で使用されます。 | ᤀ,ᤁ,ᤂ |
Mongolian | 縦書きで書かれるモンゴル語で使用されます。 | ᠠ,ᠡ,ᠢ |
Syriac | 古典的および現代のシリア語、また礼拝用に使用されます。 | ܐ,ܒ,ܓ |
Myanmar | ミャンマーのビルマ語と関連言語で使用されます。 | က,ခ,ဂ |
Phags_pa | 元朝時代に多言語で使用された歴史的な文字システムです。 | ꡀ,ꡁ,ꡂ |
NKo | 西アフリカのンコ語で使用されます。 | ߊ,ߋ,ߌ |
Ol_Chiki | インドのサンタリ語で使用されます。 | ᱚ,ᱛ,ᱜ |
下のリンクはすべての有効な値のリストです。
https://tc39.es/proposal-regexp-unicode-property-escapes/#table-unicode-script-values
\p{バイナリプロパティ}
\p{バイナリプロパティ}
と書くとバイナリプロパティがtrueな文字にマッチします。
let regex;
regex = /\p{Alphabetic}/u;
regex.test('a');// -> true
regex.test('अ');// -> true
// アルファベットにマッチ
regex = /\p{White_Space}/u;
regex.test(' ');// -> true
regex.test('\t');// -> true
// 空白にマッチ
regex = /\p{Lowercase}/u;
regex.test('a');// -> true
regex.test('γ');// -> true
/\p{Emoji}/u.test('🤪');
regex = /\p{Math}/u;
regex.test('Σ');// -> false
regex.test('×');// -> true
// 算数の記号にマッチするはず
その他
AI生成です。こんなにAIを使った記事は過去にないんじゃないかな。
プロパティ名 | 説明 | 例 |
---|---|---|
Alphabetic | アルファベットの一部である文字に対してtrueになります。 | A,Б,あ |
White_Space | 空白とみなされる文字に対してtrueになります。 | スペース,タブ,改行 |
Uppercase | 大文字のアルファベット文字に対してtrueになります。 | A,Б,Α |
Lowercase | 小文字のアルファベット文字に対してtrueになります。 | a,б,α |
Numeric | 数字や数値の文字に対してtrueになります。 | 0-9,๙ |
ID_Start | プログラミング言語で識別子を開始できる文字に対してtrueになります。 | A,_,α |
ID_Continue | 識別子の最初の文字以降に続けられる文字に対してtrueになります。 | 0,1,_ |
Emoji | 絵文字として定義されている文字に対してtrueになります。 | 😊,🍎,🚗 |
Math | 数学記号として使用される文字に対してtrueになります。 | +,×,∫ |
Diacritic | 基本文字の音を変更する文字に対してtrueになります。 | ´,^ |
Case_Ignorable | 大文字小文字を区別する比較で無視される文字に対してtrueになります。 | ',˘ |
Default_Ignorable_Code_Point | 表示に無視されるべき文字に対してtrueになります。 | U+200D |
Grapheme_Base | 単独のグラフェムとして機能する文字に対してtrueになります。 | A,क,あ |
Grapheme_Extend | グラフェムを拡張する文字に対してtrueになります。 | ´,़ |
Quotation_Mark | 引用符として使用される文字に対してtrueになります。 | ",‘,» |
Dash | ダッシュとして機能する文字に対してtrueになります。 | -,–,— |
Hex_Digit | 16進数で有効な文字に対してtrueになります。 | 0-9,A-F,a-f |
Logical_Order_Exception | テキストの論理順序に例外となる文字に対してtrueになります。 | 一部のインド母音 |
Soft_Dotted | 軟点を持つ文字に対してtrueになります。 | i,j |
Variation_Selector | 他の文字の表示に変化を示す文字に対してtrueになります。 | U+FE0F |
全プロパティのリストです。scと違ってみただけじゃなんだか分からないけどね。
https://tc39.es/proposal-regexp-unicode-property-escapes/#table-binary-unicode-properties
vフラグ
本当の最後です。今までのが嘘とは言わない。vフラグはuフラグの拡張で、uフラグで使える機能に加える形になります。
書記素クラスタ
まず「グ」という文字は信じられないと思いますが一文字です。もちろん大半の人はU+FF77
(ク)U+FF9E
(゙)の二文字だと勘違いしていたと思いますが。
書記素クラスタはこのように2文字(以上)を1文字にまとめて文字の境界を決めるシステムです。カーソルを動かしたり、文字を数えたりするときに良かったりします。
vフラグはそういう文字を判定するときに使います。
\p{binaryUnicodePropertyOfStrings}
いままではコードごとに与えられたプロパティを使えばよかったのですが(例えば文字「a」のScript(sc)プロパティの値はLatinです)、2文字ひとセットとなるとまた違った対応が必要です。
なのでそういう文字をリスト化して正規表現で使えるようにしました。それがbinary Unicode property of string
です。すごく長くて読みずらいので書記素プロパティと呼びます。
/\p{Basic_Emoji}/v.test('🖱️');// -> true
// ベーシックな絵文字
/\p{RGI_Emoji_Flag_Sequence}/v.test('🇯🇵');// -> true
// 国の文字にマッチ
全種類
コード | 説明 | 説明 |
---|---|---|
Basic_Emoji | 単一のUnicodeコードポイントで表される基本的な絵文字。 | 😀,❤️,🔥 |
Emoji_Keycap_Sequence | 数字や記号にキーキャップ記号を組み合わせた絵文字。 | 1️⃣,#️⃣ |
RGI_Emoji_Modifier_Sequence | 絵文字の基本形に肌の色などの修飾子を加えたもの。 | 👍🏽,🙋🏿 |
RGI_Emoji_Flag_Sequence | 地域を表すインジケーター記号を2つ組み合わせて国旗を表す絵文字。 | 🇺🇸,🇯🇵,🇫🇷 |
RGI_Emoji_Tag_Sequence | タグ文字を使って特定の地域や意味を表す絵文字(例:海賊旗や州旗など)。 | 🏴☠️,🏴💻 |
RGI_Emoji_ZWJ_Sequence | 絵文字同士をゼロ幅接合子(ZWJ)で繋いで1つの絵文字として表示するもの。 | 👨👩👧,🧑⚕️ |
RGI_Emoji | 「一般的な利用が推奨される絵文字」。上記すべてのカテゴリを含む。 | 👩🚀,🏳️🌈,🐶 |
AI生成です。みんなが好きかは知りませんが僕は好きです。
[&&--\q{}]
(今のところ)三つの記号が追加されます。
a&&b
はabどちらも当てはまるとマッチ、a--b
はaに当てはまってbに当てはまらないものにマッチ\q{ab}
はabという文字にマッチします。
まぁまったくわからないので例を出します。
let regex;
regex = /[\w&&a]/gv;
console.log('abc123'.match(regex));// a
// \wだけどaじゃないものにマッチ
regex = /[\w--[a13]]/gv;
console.log('abc123'.match(regex));// b, c, 2
// 新しく中に入れ子するのもあり
regex = /[\q{ac|ca}]/gv;
console.log('aca'.match(regex));// ac, ca
// \q{文字列|文字列|...}という形で使う。
さっきの書記素プロパティと合わせて使うと\q{}
は本領を発揮します。
/[\p{RGI_Emoji_Flag_Sequence}--\q{🇺🇸}]/v.test('🇯🇵(日本)');// -> true
/[\p{RGI_Emoji_Flag_Sequence}--\q{🇺🇸}]/v.test('🇺🇸(アメリカ)');// -> false
こうすると🇺🇸以外の国にマッチするようになります。\q{}を使って一文字にまとめないとエラーになります。
その他
その他のその他とかふざけてんのかって怒るほどの文量はないので勘弁してね
エスケープ
エスケープしていい文字とダメな文字があります。こちらを参照して表が見えるまで下にめくってください。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Regular_expressions/Literal_character#%E8%A7%A3%E8%AA%AC
おしまい
疲れた。