內容

名稱

charnames - 存取 Unicode 字元名稱和命名字元序列;也定義字元名稱

語法

use charnames ':full';
print "\N{GREEK SMALL LETTER SIGMA} is called sigma.\n";
print "\N{LATIN CAPITAL LETTER E WITH VERTICAL LINE BELOW}",
      " is an officially named sequence of two Unicode characters\n";

use charnames ':loose';
print "\N{Greek small-letter  sigma}",
       "can be used to ignore case, underscores, most blanks,"
       "and when you aren't sure if the official name has hyphens\n";

use charnames ':short';
print "\N{greek:Sigma} is an upper-case sigma.\n";

use charnames qw(cyrillic greek);
print "\N{sigma} is Greek sigma, and \N{be} is Cyrillic b.\n";

use utf8;
use charnames ":full", ":alias" => {
  e_ACUTE => "LATIN SMALL LETTER E WITH ACUTE",
  mychar => 0xE8000,  # Private use area
  "自転車に乗る人" => "BICYCLIST"
};
print "\N{e_ACUTE} is a small letter e with an acute.\n";
print "\N{mychar} allows me to name private use characters.\n";
print "And I can create synonyms in other languages,",
      " such as \N{自転車に乗る人} for "BICYCLIST (U+1F6B4)\n";

use charnames ();
print charnames::viacode(0x1234); # prints "ETHIOPIC SYLLABLE SEE"
printf "%04X", charnames::vianame("GOTHIC LETTER AHSA"); # prints
                                                         # "10330"
print charnames::vianame("LATIN CAPITAL LETTER A"); # prints 65 on
                                                    # ASCII platforms;
                                                    # 193 on EBCDIC
print charnames::string_vianame("LATIN CAPITAL LETTER A"); # prints "A"

說明

使用 pragma use charnames 可存取 Unicode 字元和命名字元序列的名稱,並允許您定義自己的字元和字元序列名稱。

所有形式的 pragma 都能使用以下 3 個函式

從 Perl v5.16 開始,雙引號字串中任何出現 \N{CHARNAME} 序列的狀況,如果尚未使用不同的引數載入此模組,就會自動載入此模組,並使用引數 :full:short(如下所述),以便將命名的 Unicode 字元編譯到字串中的位置。在 v5.16 之前,需要明確的 use charnames 才能啟用此用法。(不過,在 v5.16 之前,"use charnames ();" 這個形式並未啟用 \N{CHARNAME}。)

請注意,\N{U+...},其中 ... 是十六進位數字,也會將字元插入字串中。它插入的字元是 Unicode 代碼點(序數值)等於該數字的字元。例如,"\N{U+263a}" 是 Unicode(白色背景,黑色前景)笑臉,等同於 "\N{WHITE SMILING FACE}"。另外請注意,\N{...} 可能表示正規表示式量詞,而不是字元名稱,當 ... 是數字(或逗號分隔的數字對(請參閱 "perlreref 中的「QUANTIFIERS」),而且與此實用指令無關。

charnames 實用指令支援引數 :full:loose:short、腳本名稱和 自訂別名

如果存在 :full,則對於 \N{CHARNAME} 的展開,字串 CHARNAME 會先在標準 Unicode 字元名稱清單中查詢。

:loose:full 的變體,它允許 CHARNAME 的指定較不精確。詳細資訊請參閱 "LOOSE MATCHES"

如果存在 :short,而且 CHARNAME 的形式為 SCRIPT:CNAME,則會在腳本 SCRIPT 中將 CNAME 查詢為字母,如下一段所述。或者,如果 use charnames 與腳本名稱引數一起使用,則對於 \N{CHARNAME},名稱 CHARNAME 會在指定的腳本中(按照指定的順序)查詢為字母。自訂別名可以覆寫這些,並在 "CUSTOM ALIASES" 中說明。

對於在給定的腳本 SCRIPTNAME 中查詢 CHARNAME,此實用指令會在標準 Unicode 名稱表格中查詢名稱

SCRIPTNAME CAPITAL LETTER CHARNAME
SCRIPTNAME SMALL LETTER CHARNAME
SCRIPTNAME LETTER CHARNAME

如果 CHARNAME 全部是小寫,則會忽略 CAPITAL 變體,否則會忽略 SMALL 變體,而且 CHARNAMESCRIPTNAME 都會轉換為全部大寫以進行查詢。除此之外,如果也指定了 :loose,則兩者都會遵循 寬鬆 規則;否則遵循嚴格規則。

請注意,\N{...} 是編譯時期;它是雙引號字串中使用的特殊形式的字串常數;這表示您無法在 \N{...} 內使用變數。如果您想要類似的執行時期功能,請使用 charnames::string_vianame()

請注意,從 Perl 5.18 開始,名稱 BELL 參照 Unicode 字元 U+1F514,而不是傳統的 U+0007。對於後者,請使用 ALERTBEL

NAME 未知的狀況下使用 \N{NAME} 是語法錯誤。

對於 \N{NAME},如果啟用 use bytes 且輸入名稱為無法放入位元組(即序數大於 255)的字元,則會發生致命錯誤。

否則,任何包含 \N{字元名稱}\N{U+碼點} 的字串都會自動套用 Unicode 規則(請參閱 perlunicode 中的「位元組和字元語意」)。

寬鬆比對

透過指定 :loose,會選取 Unicode 的 寬鬆字元名稱比對 規則,而非一般使用的嚴格精確比對。這表示 字元名稱 不必指定得如此精確。大小寫無關緊要(如上所述,腳本除外),底線也不重要,唯一重要的連字號是名稱中字首或字尾的連字號(有一個例外:U+1180 韓文字母中聲 O-E 中的連字號很重要)。此外,不與連字號相鄰的空白也不重要。官方 Unicode 名稱在使用連字號與空白分隔字元組時變化很大,而這個選項讓您不必過於在意。非中介連字號之所以重要的原因,是因為 U+0F60 藏文字母 -A 與 U+0F68 藏文字母 A 等案例。此處的連字號很重要,連字號前的空白也很重要,因此兩者都必須包含。

:loose 會讓查詢速度比 :full 慢 2 到 3 倍,但對您來說可能值得權衡。每次個別查詢花費的時間都很少,而且結果會快取,因此速度差異只會在查詢許多不同拼法的程式中成為一個因素,而且可能只會在透過 vianame()string_vianame() 進行查詢時發生,因為 \N{...} 查詢是在編譯時完成的。

別名

從 Unicode 6.1 和 Perl v5.16 開始,Unicode 定義許多以前是 Perl 擴充功能的縮寫和名稱,以及 Perl 以前不接受的一些其他名稱。清單太長,無法在此處重製,但您可以從 Unicode 網站取得完整清單:http://www.unicode.org/Public/UNIDATA/NameAliases.txt

較早版本的 Perl 接受幾乎所有 6.1 名稱。這些名稱在這個 pod 的 v5.14 版本中記載得最為詳細:https://perldoc.dev.org.tw/5.14.0/charnames.html#ALIASES

自訂別名

您可以新增自訂別名至標準 (:full) Unicode 命名慣例。別名會覆寫任何標準定義,因此,如果您夠扭曲,您可以變更 "\N{LATIN CAPITAL LETTER A}" 的意思為 "B" 等。

別名必須以字母開頭。之後,每個別名可以包含任何單字 (\w) 字元、空白 (U+0020)、連字號減號 (U+002D)、左括弧 (U+0028) 和右括弧 (U+0029) 的組合。後兩個字元不應出現在名稱中,而且僅保留以維持向下相容性,且可能會在未來的 Perl 版本中棄用並移除,因此請勿將它們用於新名稱。(更精確地說,您指定的某個名稱的第一個字元必須符合 \p{ID_Start}\p{Alphabetic}\p{Gc=Letter} 的所有條件。這可確保它符合任何合理的人會視為字母字元的條件。而且,符合 \w 的延續字元也必須符合 \p{ID_Continue}。)從 Perl v5.18 開始,可以採用符合上述條件的任何 Unicode 字元;在此之前,僅可接受 Latin1 範圍的字元。

別名可以對應至官方 Unicode 字元名稱(而非寬鬆比對名稱)或數字碼點(序數)。後者可用於指定 Unicode 私人使用區域(例如 U+E800 至 U+F8FF)中碼點的名稱。數字碼點必須是非負整數,或以 "U+""0x" 開頭的字串,其餘部分視為十六進位整數。文字數字常數必須為未簽署;如果它有前導零或包含非十進位十六進位數字,則會將它解譯為十六進位;否則,會將它解譯為十進位。如果它以 "U+" 開頭,則會將它解譯為 Unicode 碼點;否則,會將它解譯為原生碼點。(只有小於 256 的碼點在 Unicode 和原生碼點之間會有差異。)因此,U+41 永遠是拉丁字母「A」;但 0x41 在 EBCDIC 平台上可以是「不換行空白」。

別名可以透過使用匿名雜湊新增

use charnames ":alias" => {
    e_ACUTE => "LATIN SMALL LETTER E WITH ACUTE",
    mychar1 => 0xE8000,
    };
my $str = "\N{e_ACUTE}";

或透過使用包含別名的檔案新增

use charnames ":alias" => "pro";

這會嘗試從 @INC 路徑讀取 "unicore/pro_alias.pl"。此檔案應以純粹的 perl 回傳清單

(
A_GRAVE         => "LATIN CAPITAL LETTER A WITH GRAVE",
A_CIRCUM        => "LATIN CAPITAL LETTER A WITH CIRCUMFLEX",
A_DIAERES       => "LATIN CAPITAL LETTER A WITH DIAERESIS",
A_TILDE         => "LATIN CAPITAL LETTER A WITH TILDE",
A_BREVE         => "LATIN CAPITAL LETTER A WITH BREVE",
A_RING          => "LATIN CAPITAL LETTER A WITH RING ABOVE",
A_MACRON        => "LATIN CAPITAL LETTER A WITH MACRON",
mychar2         => "U+E8001",
);

這兩種方法都會自動插入 ":full" 作為第一個參數(如果沒有給定其他參數),而且你也可以明確地給出 ":full",例如

use charnames ":full", ":alias" => "pro";

":loose" 對這些沒有影響。輸入名稱必須完全匹配,使用 ":full" 規則。

此外,這兩種方法目前只允許命名單個字元。若要命名一系列字元,請使用 自訂翻譯器(如下所述)。

charnames::string_vianame(name)

這是 \N{...} 的執行時間等效項。name 可以是任何表達式,其評估為 \N{...}:full 選項接受的名稱,以 charnames。此外,作用域中控制 "use charnames" 的任何其他選項都適用,例如 :loose 或任何 腳本清單、:short 選項,或你可能已定義的 自訂別名

唯一的差異是,由於 string_vianame 是執行時間,而 \N{} 是編譯時間。你無法在 \N{} 內插值(因此 \N{$variable} 不起作用);而且如果輸入名稱未知,string_vianame 會傳回 undef,而不是語法錯誤。

charnames::vianame(name)

這類似於 string_vianame。主要區別在於,在大多數情況下,vianame 會傳回序數碼點,而 string_vianame 會傳回字串。例如,

printf "U+%04X", charnames::vianame("FOUR TEARDROP-SPOKED ASTERISK");

會印出「U+2722」。

這導致其他兩個差異。由於會傳回單一碼點,因此函式無法處理命名字元序列,因為這些序列由多個字元組成(它會為這些傳回 undef。而且,碼點可以是任何字元的碼點,即使是 use bytes pragma 下不合法字元的碼點,

請參閱 "BUGS",了解行為與上述描述不同的情況。

charnames::viacode(code)

傳回數字碼點所指示的字元的完整名稱。例如,

print charnames::viacode(0x2722);

會印出「FOUR TEARDROP-SPOKED ASTERISK」。

傳回的名稱是碼點的「最佳」(定義如下)官方名稱或別名(如果可用);否則,是為其定義的自訂別名(如果已定義);否則,是 undef。這表示你的別名只會傳回沒有官方 Unicode 名稱(或別名)的碼點,例如私人使用碼點。

如果你為碼點定義多於一個名稱,則無法確定會傳回哪一個名稱。

如前所述,如果代碼點沒有已知的名稱,函數會傳回 undef。在 Unicode 中,這些名稱的正確名稱是空字串,而 undef 會字串化為空字串。(如果你要求超出 U+10FFFF 的合法 Unicode 最大值,而且你沒有指定別名,你會得到 undef 和一個警告。)

輸入數字必須是非負整數,或以 "U+""0x" 開頭的字串,其餘部分視為十六進位整數。文字數字常數必須是未簽署的;如果它有前導零或包含非十進位的十六進位數字,它將被解釋為十六進位;否則,它將被解釋為十進位。如果它以 "U+" 開頭,它將被解釋為 Unicode 代碼點;否則,它將被解釋為本機代碼點。(只有小於 256 的代碼點才能在 Unicode 和本機代碼點之間有所不同。)因此,U+41 永遠是拉丁字母「A」;但 0x41 可以在 EBCDIC 平台上是「不換行空白」。

如上文在 "別名" 下所述,Unicode 6.1 為某些代碼點定義了額外的名稱(同義詞或別名),其中大多數已經作為 Perl 擴充功能提供。所有這些都由 \N{...} 和此模組中的其他函數接受,但 viacode 必須選擇一個名稱來傳回給定的輸入代碼點,因此它會傳回「最佳」名稱。要了解這是如何運作的,瞭解更多關於 Unicode 名稱屬性的資訊會很有幫助。所有代碼點實際上只有一個名稱,在將字元指定給代碼點後,這個名稱(從 Unicode 2.0 開始)永遠不會改變。但在指定名稱時會發生錯誤,例如,有時在標準發布期間會發生文員錯誤,導致字詞拼寫錯誤,而且沒有辦法更正這些錯誤。最終建立了 Name_Alias 屬性來處理這些情況。如果名稱錯誤,將會使用 Name_Alias 為其發布更正的同義詞。viacode 會將更正的同義詞作為代碼點的「最佳」名稱傳回。(儘管尚未發生,但仍有可能需要更正更正本身,因此可以為該代碼點建立另一個 Name_Alias;viacode 會傳回最新的更正。)

每個控制字元(例如換行符)的 Unicode 名稱都是空字串。然而,幾乎所有控制字元都有其他標準指定的名稱,例如 ASCII 標準,或在一般使用中。viacode 將這些名稱作為可用的「最佳」名稱傳回。Unicode 6.1 已為每個控制字元建立 Name_Alias,包括備用名稱,例如換行符。viacode 使用原始名稱「換行符」,而不是備用的「換行符」。類似地,為 U+FEFF 傳回的名稱是「零寬度不換行空白」,而不是「位元組順序標記」。

在 Unicode 6.1 之前,4 個控制字元 U+0080、U+0081、U+0084 和 U+0099 沒有名稱或別名。為了保持向後相容性,你為這些代碼點定義的任何別名都將由這個函數傳回,而不是官方名稱。

某些代碼點也有簡稱,例如「LF」或「NL」。viacode 永遠不會傳回這些。

由於在未來的 Unicode 版本中可能會新增名稱修正,因此 viacode 傳回的名稱可能會因此而變更。這是罕見的事件,但確實會發生。

自訂轉譯器

\N{...} 逸出的轉譯機制是通用的,並未硬編碼到 charnames.pm 中。模組可以在(use 使用模組的範圍內)使用下列的魔法咒語安裝自訂轉譯器

sub import {
    shift;
    $^H{charnames} = \&translator;
}

在此,translator() 是將 CHARNAME 作為引數的子常式,並傳回文字以插入到字串中,取代 \N{CHARNAME} 逸出。

這是唯一可以建立自訂命名之代碼點順序的方法。

由於要插入的文字在 bytes 模式中和在模式外應該不同,因此該函數應該檢查 bytes 旗標的目前狀態,如下所示

use bytes ();                      # for $bytes::hint_bits
sub translator {
    if ($^H & $bytes::hint_bits) {
        return bytes_translator(@_);
    }
    else {
        return utf8_translator(@_);
    }
}

請參閱上方的 "自訂別名" 以了解 CHARNAME 的限制。

當然,也需要覆寫 vianameviacodestring_vianame

錯誤

vianame() 通常會傳回序數代碼點,但當輸入名稱為 U+... 格式時,它會傳回 chr。在此情況下,如果 use bytes 生效,且字元無法放入位元組中,它會傳回 undef 並發出警告。

由於轉譯函數的評估(請參閱 "自訂轉譯器")發生在編譯(字串文字)的過程中,因此轉譯函數不應執行任何 evalrequire。此限制應在未來的 Perl 版本中解除(但優先順序較低)。