認識 Unicode
July 2, 2022現今的開發者若要處理文字,不免會遇上 Unicode、編碼等問題,規則表示式現今包含了對 Unicode 的支援,各語言則以不同的方式或選項實現,若要使用規則表示式處理 Unicode 等文字問題,必須對 Unicode 有基本的認識。
Unicode 與 UCS-2
字元集是一組符號的集合,字元編碼是字元實際儲存時的位元組格式,如前面的範例看到的,讀取時使用的編碼不正確,編輯器會解讀錯誤而造成亂碼,在還沒有 Unicode 與 UTF(Unicode Transformation Format)前,各個系統間編碼不同而造成的問題,困擾著許多開發者。
要統一編碼問題,必須統一管理符號集合,也就是要有統一的字元集,ISO/IEC 與 Unicode Consortium 兩個團隊都曾經想統一字元集,而 ISO/IEC 在 1990 年先公佈了第一套字元集的編碼方式 UCS-2,使用兩個位元組來編碼字元。
字元集中每個字元會有個編號作為碼點(Code point),實際儲存字元時,UCS-2 以兩個位元組作為一個碼元(Code unit),也就是管理位元組的單位;最初的想法很單純,令碼點與碼元一對一對應,在編碼實作時就可以簡化許多。 後來 1991 年 ISO/IEC 與 Unicode 團隊都認識到,世界不需要兩個不相容的字元集,因而決定合併,之後才發佈了 Unicode 1.0。
Unicode 與 UTF
由於越來越多的字元被納入 Unicode 字元集,超出碼點 U+0000 至 U+FFFF 可容納的範圍,因而 UCS-2 採用的兩個位元組,無法對應 Unicode 全部的字元碼點,後來在 1996 年公佈了 UTF16。
UTF-16 除了沿用 UCS-2 兩個位元組的編碼部份之外,超出碼點 U+0000 至 U+FFFF 的字元,採用四個位元組來編碼,因而視字元是在哪個碼點範圍,對應的 UTF-16 編碼可能是兩個或四個位元組,也就是說採用 UTF-16 儲存的字元,可能會有一個或兩個碼元。
UTF-16 至少使用兩個位元組,然而對於 +/?@#$ 或者是英文字元等,也使用兩個位元組,感覺蠻浪費儲存空間,而且不相容於已使用 ASCII 編碼儲存的字元,Unicode 的另一編碼標準 UTF-8 用來解決此問題。
UTF-8 儲存字元時使用的位元組數量,也是視字元落在哪個 Unicode 範圍而定,從 UTF-8 的觀點來看,ASCII 編碼是其子集,儲存 ASCII 字元時只使用一個位元組,其他附加符號的拉丁文、希臘文等,會使用兩個位元組(例如 π),至於中文部份,UTF-8 採用三個位元組儲存,更罕見的字元,可能會用到四到六個位元組,例如微笑表情符號 U+1F642,就使用了四個位元組。
簡單來說,Unicode 對字元給予編號以便進行管理,真正要儲存字元時,可以採用 UTF-8、UTF-16 等編碼為位元組。
位元組?碼元?碼點?
由於不同語言在不同的時間點誕生、跨越不同的時間區段發展,對於 Unicode 採用的時程也各不相同,在面對需要處理 Unicode 文字的場合,必須先搞清楚語言的某些資料型態,是儲存位元組、碼元還是碼點,例如,C/C++ 的 char
儲存的是位元組、碼元還是碼點?Java 的 char
儲存的是位元組、碼元還是碼點?Python 的字串呢?JavaScript 的字串呢?
另一方面,在一些字串表示法方面,例如 \u0000
,究竟是指碼元還是碼點呢?
這些在處理文字或運用規則表示式時,若要面對 Unicode,都是必須先釐清之事,後續在談到相關語言對規則表示式的支援時,必要時會做適當介紹。
UNICODE REGULAR EXPRESSIONS
Unicode 字元集為世界大部份文字系統做了整理,規則表示式是為了比對文字,兩者相遇就產生了更多的需求;為了能令規則表示式支援 Unicode,Unicode 組織在〈UNICODE REGULAR EXPRESSIONS〉做了規範。
在 Unicode 規範中,每個 Unicode 字元會隸屬於某個分類,在〈General Category Property〉可看到 Letter、Uppercase Letter 等一般分類,每個分類也給予了 L、Lu 等縮寫名稱。
舉例來說,隸屬於 Letter 分類的字元都是字母,a 到 z、A 到 Z、全形的a到z、A到Z都在 Letter 分類中,除了英文字母之外,其他如希臘字母 α、β、γ 等,也都隸屬於 Letter 分類。
有的語言可能會使用多種文字來書寫,例如日語就包含了漢字、平假名、片假名等文字,有的語言只使用一種文字,例如泰文。Unicode 將書寫組織為文字(Script)特性,可參考〈UNICODE SCRIPT PROPERTY〉。