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…)