JavaScript 使用 Unicode 編碼 編碼字串。大多數字元使用 2 個位元組編碼,但這最多只能表示 65536 個字元。
這個範圍不足以編碼所有可能的字元,因此一些罕見的字元使用 4 個位元組編碼,例如 𝒳
(數學 X)或 😄
(笑臉)、一些象形文字等等。
以下是某些字元的 Unicode 值
字元 | Unicode | Unicode 中的位元組計數 |
---|---|---|
a | 0x0061 |
2 |
≈ | 0x2248 |
2 |
𝒳 | 0x1d4b3 |
4 |
𝒴 | 0x1d4b4 |
4 |
😄 | 0x1f604 |
4 |
因此,像 a
和 ≈
等字元佔用 2 個位元組,而 𝒳
、𝒴
和 😄
的碼則較長,它們有 4 個位元組。
很久以前,在 JavaScript 語言被建立時,Unicode 編碼較為簡單:沒有 4 位元組字元。因此,某些語言功能仍會錯誤處理它們。
例如,length
認為這裡有兩個字元
alert('😄'.length); // 2
alert('𝒳'.length); // 2
…但我們可以看到只有一個,對吧?重點是 length
將 4 個位元組視為兩個 2 位元組字元。這是錯誤的,因為它們必須一起考慮(所謂的「代理對」,您可以在文章 字串 中閱讀它們)。
預設情況下,正規表示式也會將 4 位元組「長字元」視為一對 2 位元組字元。而且,就像字串一樣,這可能會導致奇怪的結果。我們稍後會在文章 集合和範圍 [...] 中看到這一點。
與字串不同,正規表示式有旗標 u
,可以解決此類問題。使用此旗標,正規表示式可以正確處理 4 位元組字元。Unicode 屬性搜尋也會變為可用,我們稍後會了解它。
Unicode 屬性 \p{…}
Unicode 中的每個字元都有很多屬性。它們描述字元屬於哪個「類別」,並包含有關它的其他資訊。
例如,如果一個字元具有 Letter
屬性,表示該字元屬於任何語言的字母表。而 Number
屬性表示它是一個數字:可能是阿拉伯數字或中文數字,依此類推。
我們可以使用屬性搜尋字元,寫成 \p{…}
。若要使用 \p{…}
,正規表示式必須有旗標 u
。
例如,\p{Letter}
表示任何語言的字母。我們也可以使用 \p{L}
,因為 L
是 Letter
的別名。幾乎每個屬性都有較短的別名。
在下面的範例中,將找到三種字母:英文、喬治亞文和韓文。
let str = "A ბ ㄱ";
alert( str.match(/\p{L}/gu) ); // A,ბ,ㄱ
alert( str.match(/\p{L}/g) ); // null (no matches, \p doesn't work without the flag "u")
以下是主要的字元類別及其子類別
- 字母
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}
等。
還有其他衍生類別,例如
字母
(Alpha
),包括字母L
,加上字母數字Nl
(例如 Ⅻ – 羅馬數字 12 的字元),加上一些其他符號其他字母
(OAlpha
)。十六進制數字
包括十六進制數字:0-9
、a-f
。- …等等。
Unicode 支援許多不同的屬性,其完整清單需要很大的空間,因此以下提供參考
- 按字元列出所有屬性:https://unicode.org/cldr/utility/character.jsp。
- 按屬性列出所有字元:https://unicode.org/cldr/utility/list-unicodeset.jsp。
- 屬性的簡短別名:https://www.unicode.org/Public/UCD/latest/ucd/PropertyValueAliases.txt。
- 以下提供 Unicode 字元的完整文字格式基礎,包含所有屬性:https://www.unicode.org/Public/UCD/latest/ucd/。
範例:十六進制數字
例如,讓我們尋找寫成 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
範例:中文字形
讓我們尋找中文字形。
有一個 Unicode 屬性 Script
(寫作系統),其值可能是:Cyrillic
、Greek
、Arabic
、Han
(中文)等,以下是完整清單。
要尋找特定寫作系統中的字元,我們應該使用 Script=<value>
,例如對於西里爾字母:\p{sc=Cyrillic}
,對於中文字形:\p{sc=Han}
,等等
let regexp = /\p{sc=Han}/gu; // returns Chinese hieroglyphs
let str = `Hello Привет 你好 123_456`;
alert( str.match(regexp) ); // 你,好
範例:貨幣
表示貨幣的字元,例如 $
、€
、¥
,具有 Unicode 屬性 \p{Currency_Symbol}
,簡短別名:\p{Sc}
。
我們使用它來尋找「貨幣,後接數字」格式的價格
let regexp = /\p{Sc}\d/gu;
let str = `Prices: $2, €1, ¥9`;
alert( str.match(regexp) ); // $2,€1,¥9
稍後,在文章 量詞 +, *, ? 和 {n} 中,我們將看到如何尋找包含多個數字的數字。
摘要
旗標 u
啟用正規表示式中 Unicode 的支援。
這表示兩件事
- 4 位元組的字元正確處理:作為單一字元,而不是兩個 2 位元組字元。
- Unicode 屬性可以用於搜尋:
\p{…}
。
使用 Unicode 屬性,我們可以尋找特定語言、特殊字元(引號、貨幣)等等的字詞。
留言
<code>
標籤,若要插入多行,請將它們包在<pre>
標籤中,若要插入超過 10 行,請使用沙盒 (plnkr、jsbin、codepen…)