ユニコード文字では、複数の文字(コードポイント)を組み合わせて1つの文字とすることができる。たとえば、人物の絵文字では、スキントーン指定文字(EMOJI MODIFIER FITZPATRICK TYPE-x)を、使って肌の色を指定できる。
かつては文字は、バイトやワードで表現されていたが、今や文字列処理は、そういう簡単なものではなくなってきた。
ここでは、ターミナル内でPowerShell(Ver.7.5)を使い、文字列を書記素単位で扱ってみる。まずは、対象となる文字列は、$xに入っているとする(写真01)。ここで入れた絵文字は、3人の人物(ADALT、BOY、GIRL)のそれぞれにスキントーンの指定があり、3人をZERO WIDTH JOINERで結合させている。1つの絵文字だが、8つのユニコードコードポイントから構成されている。
$xに対してParseCombiningCharactersメソッドを使い書記素の開始位置を$pccに記憶させておく。
$pcc=([System.Globalization.StringInfo]::ParseCombiningCharacters($x))
文字列中の書記素の開始位置が$pccに配列として記録され、書記素の数は、「$pcc.count」で求めることができる。
以後の扱いを考えると、書記素ごとにオブジェクトを作ると、以後の処理が簡単になる。
$uc=$pcc | %{$temp=[System.Globalization.StringInfo]::GetNextTextElement( $x,$_);[pscustomobject]@{code=[int[]][char[]]$temp ;letter=$temp} }
以後は、$uc.codeでUnicode文字コード、$uc.letterで書記素文字にアクセスできる。16進数で文字コードをダンプしたければ、
$uc | %{ $_.code | %{$_.ToString("X4")};" "}
とすればよい。
書記素の各Unicode文字をコードポイントで表示したい場合、StringクラスのEnumerateRunesメソッドを使うと簡単だ。前記と同じく、書記素ごとに文字をコードポイントに変換するには、
$cp=$pcc | %{$temp=[System.Globalization.StringInfo]::GetNextTextElement( $x,$_);[pscustomobject]@{code=$temp.EnumerateRunes().value ;letter=$temp} }
とする。こちらも前記と同じ方法で16進数ダンプが行える。
また、Unicode文字に対して、CharUnicodeInfoクラスのGetUnicodeCategoryメソッドを使うと、文字のカテゴリを表示できる。
$ucl=$uc[1].letter; 0..(([char[]]$ucl).count-1) | % { "$(([int][char]$ucl[$_]).tostring("X4")):$([System.Globalization.CharUnicodeInfo]::GetUnicodeCategory($ucl,$_))" }
Charクラスにも同名のメソッドがあるが、準拠しているユニコードのバージョンが異なる。CharUnicodeInfoクラスは、ユニコードのバージョンアップに追従するが、Charクラスは、古い仕様のユニコードのままになっている。
今回のタイトルネタは、アルフレッド・ベスター(Alfred Bester)の「分解された男」(創元推理文庫。原題The Demolished Man、1953年)である。