ユニコードでは複数の絵文字を結合させて
別の絵文字を表現することもある
Unicodeが一般的になって、日本語を含めて、さまざまな言語の文字を自由に使えるようになったが、「文字」を取り出す、あるいは数えるのが面倒になったのも確かだ。というのも、1つの文字が必ずしも1つのコードポイントで表現されるとは限らないからだ。
たとえば絵文字では、複数の絵文字をゼロ幅接合子(Zero Width Joiner:ZWJ、U+200D)で結合することで、別の絵文字を表現することがある。たとえば、「🐦 鳥(bird)」(U+1F426)と「🔥 火」(U+1F525)をゼロ幅接合子でつなげたものは、「🐦🔥フェニックス」(Unicode Emoji 15.1で定義)の絵文字になる。
コードだと「U+1F426」「U+200D」「U+1F525」なのだが、表示上は1つの文字に見える。なお、こうした組み合わせは、ユニコード仕様書で定められ、誰かが勝手に作っているわけではない。
漢字の場合には、異字体がある。こちらはコードポイントの後ろに「異字体セレクタ」が付く。簡単に言えば、ユニコードは32bitのコードポイントを使うが、人間が認識する文字である「書記素クラスタ」(grapheme cluster)は、複数のコードポイントから構成されることがある。文字列から、書記素クラスタを認識して境界を決定する処理を「テキスト・セグメンテーション」という。
これは人間が見たときに「1文字」に見えるようなコードポイントのつながりを認識して、切れ目を見つけるのが「テキスト・セグメンテーション」である。ユニコードの処理では、分割された1文字(人の目に見える1文字)を「書記素」(grapheme)と表現することがある。
テキスト・セグメンテーションに関しては、ユニコードでは「Unicode Standard Annex #29 (UAX#29) Unicode Text Segmentation」(https://unicode.org/reports/tr29/)に定義がある。
PowerShellなどで、文字列を正しく分割するには、.NETの「StringInfoクラス(System.Globalization)」(https://learn.microsoft.com/ja-jp/dotnet/api/system.globalization.stringinfo?view=net-8.0)を使うのが簡単だ。
まずは、文字(書記素)の先頭位置を求める。PowerShellでは、内部は、リトルエンディアンのUTF16(これをWindowsではUnicodeと呼ぶ)でエンコードされている。このため、一部のコードポイントは、サロゲートペアを使って16ビット文字コード2つで表現されている。
StringInfoクラスの「ParseCombiningCharacters」メソッド(https://learn.microsoft.com/ja-jp/dotnet/api/system.globalization.stringinfo.parsecombiningcharacters?view=net-8.0#system-globalization-stringinfo-parsecombiningcharacters(system-string))は、文字列を受け取って、その書記素の先頭部分の位置を返すものだ。これを使うことで、文字の「境界」を得られる。
具体的には、PowerShellのコマンドラインで以下のようにする。
[System.Globalization.StringInfo]::ParseCombiningCharacters(<文字列>)
このメソッドは、書記素の先頭の位置を返す。たとえば、「葛󠄀-葛」という文字列は、コードポイントとしてみると、以下の図のようになっている。
この文字列に対して、ParseCombiningCharactersを実行すると、「0、3、4」という位置が返る。これは、文字の先頭が0文字目、3文字目、4文字目にあるということだ。入力が面倒そうだが、正直にキーを打つ必要はなく、先頭部分は、「“[stringinfo”+Tabキー」で、後半は「“]::p”+Tabキー」で開きカッコまで補完できる。
なお、いわゆる文字数(書記素クラスタの数)は、ParseCombiningCharactersがいくつ整数を出力しているかを数えるだけでいいので、
([System.Globalization.StringInfo]::ParseCombiningCharacters($x)).Length
で求めることができる(コマンドラインならMeasure-Objectコマンドを使うこともできる)。
この連載の記事
-
第449回
PC
WSLはプレビュー版でGUIでの設定が加わった! リリース2.3.xの新機能を見る -
第448回
PC
PowerShellで面倒なオブジェクトはPSCustomObjectに変換するのが早道 -
第447回
PC
この秋登場のWindows 11の新バージョン、Ver.24H2の状況を見る -
第446回
PC
Windows 11のフォトアプリがUWPからWin32アプリになったことで今更わかるUWPの問題点 -
第445回
PC
次期Windows 11ではAndroidのファイルをエクスプローラーからアクセス可能になる -
第444回
PC
外部ファイルをExcelに読み込む際の作業を効率化するPower Queryの活用 -
第443回
PC
Windows Terminalで採用されたCascadia Codeフォントを使うとプログラムを書くとき断然見やすい -
第442回
PC
Copilot+ PCで実現されるローカル推論で「対クラウド企業」を指向するMicrosoft -
第441回
PC
WSL以前から40年以上続く、Windows(Microsoft)とUNIXとの関わり -
第440回
PC
そもそも「Copilot+ PC」とは何なのか? - この連載の一覧へ