Movatterモバイル変換


[0]ホーム

URL:


信之 岩永, profile picture
Uploaded by信之 岩永
PPTX, PDF3,416 views

Unicode文字列処理

https://edge.connpass.com/event/161663/ にて登壇。今現在、Unicodeという文字規格には13万個以上の文字が収録されています。それぞれの文字には文字のカテゴリー、文字と文字の連結方法、左右どちらから読むかなど、様々な付帯情報も定められています。英語でドキュメントがあり、例えばアラビア語を読めなくてもアラビア文字のレンダリング処理を書ける程度には詳細な仕様が書かれています。本セッションでは、このUnicodeの仕様の概要と、それをプログラム(主にUnity上でのC#を想定)的に処理する際の注意点などについて説明します。

Embed presentation

Downloaded 10 times
文字列処理岩永 信之
自己紹介• 普段はスマホゲーム作ってます(常時求人中)ジャンル : RPG公式Twitter : https://twitter.com/majo_meikyuジャンル : ストラテジー共同開発 : 株式会社gumi公式サイト : http://www.cryuni.com/http://orange-cube.jp/C#な会社ですDocker, k8s, .NET Core 3.1
今日の話「文字」の話をします。
時代背景など• 多くが西欧の国• ほっとくとラテン文字ばかり優遇• 普及期の非ラテン文字 ≒ 日本• 非ラテン文字の中ではかな漢字はだいぶこなれてる方• 日本がやらかした黒歴史がそのままUnicodeに残ってたりも• 商機のわりに未熟な文字あり• アラブ(石油王)とか• インド(GDP伸び盛り)とかGDP推移※※ http://www.garbagenews.net/archives/1335765.htmlWindows 95(PCの一般家庭普及)Unicode 1.0制定 絵文字
文字?• ここでいう文字とは?• letter … 「a」とか「あ」とか音に出して読める文字• character … 記号類、制御文字なども含む• 文字コードの「文字」はcharacterあんまり文字っぽくない「character」の例※:0000 … ヌル文字 (「どの文字でもない」を表す。大体は文字列末尾を検出するための番兵)00D0 … 改行0301 … acuteアクセント「 ́ 」 (1文字前のletterの上に乗っかる)8205 … zero width joiner (前後の文字を分割しないようにする)8207 … right to left mark (この文字以降を右書きにする)※ 文字がらみで16進数が出てきたら符号点(文字に割り当てられた数字)のことだと思ってください
改めて今日の話• コンピューター内で文字(character)がどう扱われているか• Unicode前提• まず、Unicodeの話から• いろいろとある文字の面倒事• ラテン文字しか受け付けないプログラムが結構ある理由• 日本語を受け付けるプログラムでも絵文字が怪しいことがある理由• C#で何も考えずにstringを使うと遅いことが結構ある理由• 絵文字が踏み抜いちゃった地雷• 日本語とかまだ楽な部類という話(アラビア文字を例に)
改めて今日の話• コンピューター内で文字(character)がどう扱われているか• Unicode前提• まず、Unicodeの話から• いろいろとある文字の面倒事• ラテン文字しか受け付けないプログラムが結構ある理由• 日本語を受け付けるプログラムでも絵文字が怪しいことがある理由• C#で何も考えずにstringを使うと遅いことが結構ある理由• 絵文字が踏み抜いちゃった地雷• 日本語とかまだ楽な部類という話(アラビア文字を例に)• 文字は国・文化に直結してるのでうかつなことすると「よろしい、ならば戦争だ」• 今日持ち帰っていただく感想はたぶん「面白いけど関わりたくない」
文字コード符号点と符号化方式
符号点と符号化方式• 符号点 (code point)• どの文字にどの番号を振るか※• 文字符号化形式 (character encoding)• その番号をどうやって記録するかa … 61あ … 3042😊 … 1F60A※ 本稿では常に16進数で表記符号点 UTF-8 UTF-16 UTF-3261 61 0061 000000613042 E3 81 82 3042 000030421F60A F0 9F 98 8A D83D DE0A 0001F60A例:例:この意味では今時「Unicode一択」(レガシー資産がなければ他の文字コードのことは考えなくていい)この意味では同じUnicodeでも複数の符号化形式がある
符号点• 符号点 (code point)• どの文字にどの番号を振るか• 仕様上は16進数で0~10FFFFまでの約111万文字• 実際に使われているのは137,928文字 (Unicode 12.0時点)a … 61あ … 3042😊 … 1F60A例:
符号化方式• Unicodeでは大きく分けて3種類• UTF-8 : 符号点あたり1~4バイト(8~32ビット)の可変長• UTF-16 : 符号点あたり2か4バイトの可変長(ただし、大半の文字が2バイト(16ビット))• UTF-32 : 4バイト(32ビット)固定• 細かくはエンディアンによってさらに分かれる (Big/Little)• UTF-16 BE, UTF-16 LE, UTF-32 BE, UTF-32 LE符号点 UTF-8 UTF-16 UTF-3261 61 0061 000000613042 E3 81 82 3042 000030421F60A F0 9F 98 8A D83D DE0A 0001F60A30 42 / 42 3000 01 F6 0A / 0A F6 01 00例:
Unicodeの符号化方式• Unicodeでは大きく分けて3種類• UTF-8 : 符号点あたり1~4バイト(8~32ビット)の可変長• UTF-16 : 符号点あたり2か4バイトの可変長(ただし、大半の文字が2バイト(16ビット))• UTF-32 : 4バイト(32ビット)固定• この辺りに「ラテン文字しか受け付けない」、「絵文字の処理がおかしい」の原因あり• どうしてこうなったかはちょっと歴史の話が必要
ASCIIコード原初の7ビット文字コード
ASCIIコード• 1963年にアメリカで規格化された文字コード• 7ビット(128文字)0 1 2 3 4 5 6 7 8 9 A B C D E F0 NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI1 DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US2 SP! " # $ % & ' ( ) * + , - . /3 0 1 2 3 4 5 6 7 8 9 : ; < = > ?4 @ A B C D E F G H I J K L M N O5 P Q R S T U V W X Y Z [ ⧵ ] ^ _6 ` a b c d e f g h i j k l m n o7 p q r s t u v w x y z { | } ~ DELASCII = American Standard Code for Information Interchange の略
ASCIIコード• 1963年にアメリカで規格化された文字コード• コンピューターの大量生産が始まった時期・場所= 世界標準規格の元になってる• 今でもASCII• ASCIIしか受け付けないプロトコルが普通に現存• インターネットで流通している文字の大部分がASCII• 非ラテン文字の文字コードも「ASCII互換」が重要視される• 最初の128文字がASCIIと同じ• ASCIIバイト列を無変換で受け付ける
インターネット上の大部分がASCII• 例えばHTTP 1.1ヘッダーHTTP/1.1 200 OKDate: Mon, 27 Jan 2020 03:45:20 GMTVary: Accept-Encoding,Cookie,AuthorizationServer: ATS/8.0.5X-ATS-Timestamp: 1580096720Content-Type: text/html; charset=UTF-8X-Powered-By: PHP/7.2.26-1+0~20191218.33+debian9~1.gbpb5a340+wmf1X-Content-Type-Options: nosniffP3P: CP="See https://ja.wikipedia.org/wiki/Special:CentralAutoLogin/P3P for more info."Content-language: jaContent-Encoding: gzipLast-Modified: Sun, 19 Jan 2020 07:05:51 GMTBackend-Timing: D=196662 t=1579418807535784X-Varnish: 152932621 767971738Age: 28457X-Cache: cp5011 miss, cp5012 hit/40X-Cache-Status: hit-frontServer-Timing: cache;desc="hit-front"Strict-Transport-Security: max-age=106384710; includeSubDomains; preloadX-Client-IP: 118.238.249.198Cache-Control: private, s-maxage=0, max-age=0, must-revalidateAccept-Ranges: bytesContent-Length: 168955Connection: keep-alive何語のページを見ようと、先頭には必ずこんな感じのヘッダーが入ってる(この部分は全部ASCII)
インターネット上の大部分がASCII• 例えばHTML(表示上)我、15億人の文字ぞ?ラテン文字ごときがそんな?
インターネット上の大部分がASCII• 例えばHTML(ソースコード)この辺り全部ASCII表示上はあんなに漢字だらけなのに…ソースコード上はASCII : 42万文字非ASCII : 3万文字
インターネット上の大部分がASCII• 例えばソースコード• キーワードとかは全部ASCII• 変数名に非ASCII文字を使う人は極めて少数• 使ってよくてもIMEがめんどくさい• 非ASCII文字はほぼ文字列リテラル中のみusing System;var line = Console.ReadLine();var x = int.Parse(line);$"{x} × {x} = {x * x}"この例で言うと非ASCII文字は×(乗算記号、00D7)のみ• 昔のコンパイラーはリテラル・コメント以外の非ASCII文字を受け付けないことも多かった• 最近のコンパイラーも、まずASCII文字だけを処理するFast Pathがあったり
ASCII互換大事(再)• 流通の大部分を占めるASCII文字列の処理は重要• ASCIIを無変換で扱いたい• UTF-8 (後述)が主流になったのもこれが理由• C#とかJavaのcharはUTF-16 (ASCIIから変換が必要)• 文字列処理が遅い原因に
Unicode世界中の文字を1つの文字コード体系に
Unicodeの符号点(一例)• 0~8F: ラテン文字。ASCII互換• 10~FF: áとか、西欧で使う装飾付きラテン文字(通称Latin-1)• 250~2AF: 国際音声記号• 370~3FF: ギリシャ文字 Ελληνικά• 400~52F: キリル文字 Кириллица• 600~6FF: アラビア文字 ‫اللغة‬• 3040~30FF: ひらがな・カタカナ• 4E00~9FFF: 漢字当初、2万文字あれば足りると思ってたUnicodeも2バイト固定を目指してた
2バイト(6万5千文字)では足りない• 世界中の文字を全部入れたい• マイナーな漢字も入れようとすると4万文字くらい増えた• 古代文字も全部入れたいとか言い出すとどんどん増える• ということで追加• 0~FFFF: 基本多言語面(前項のラテン文字~基本漢字)• 10000~1FFFF: 追加多言語面(古代文字や記号、絵文字)• 20000~2FFFF: 追加漢字面• 30000~3FFFF: 第三漢字面(古代の漢字とか甲骨文字)• E0000~EFFFF: 追加特殊用途面(絵文字装飾とか用の特殊文字)例えばヒエログリフ(𓄿𓄿𓄿)とか楔形文字( )とか
Unicodeの符号化方式• UTF-8• ASCII互換で、1~4バイトの可変長• ASCIIだけ1バイト、かな漢字は3バイト• UTF-16• Unicode、当初は2バイト固定長のつもりだった• 基本多言語面(0~FFFF)の文字は符号点そのまま• 追加面の文字をD800~DBFFとDC00~DFFFの範囲の2文字ペアで表現• UTF-32• 符号点そのまま4バイト固定長で記録• 13万文字しか使ってないのに常に4バイト必要さすがに無駄UTF-8とUTF-16だけ説明UTF = Unicode Transform Format
UTF-8• 1~4バイトの可変長符号化• 2バイト: ギリシャ文字、キリル文字、アラビア文字など• 3バイト: 日中韓(かな漢字、ハングル)など• 4バイト: 一部の漢字、絵文字などビット数 最小値 最大値 変換方法 ビット パターン元コード ポイント 1バイト目 2バイト目 3バイト目 4バイト目7 0000 007F そのまま xxxxxxx 0xxxxxxx11 0080 07FF 2バイト化 xxxxxxxxxxx 110xxxxx 10xxxxxx16 0800 FFFF 3バイト化 xxxxxxxxxxxxxxxx 1110xxxx 10xxxxxx 10xxxxxx21 10000 1FFFF 4バイト化 xxxxxxxxxxxxxxxxxxxxx 11110xxx 10xxxxxx 10xxxxxx 10xxxxxxASCIIはASCIIのまま2バイト目以降に1バイト目と被る値が出てこない
UTF-16• 2 or 4バイトで符号化• 2バイト: ASCII、日中韓含めて大半の文字• ASCIIにとっては不利• 日中韓にとっては有利• 4バイト: 一部の漢字、絵文字など• 4バイトになる条件はUTF-8と同じ範囲 変換方法ビット パターン元コード ポイント 1文字目 2文字目0000~D7FF,E000~FFFFそのまま xxxxxxxxxxxxxx xxxxxxxxxxxxxx10000以上 2文字使う uuuuuxxxxxxxxxxxxxxxx 110110wwwwxxxxxx 110111xxxxxxxxxx※ wwww = uuuuu - 1※• 元々2バイト固定のつもりでいたところに無理やりねじ込んだ仕様• 「2文字で2符号点を表す」的に解釈される(surrogate pair (代用対))これのせいでD800~DFFFの範囲をUnicode符号点として使えなくなった
UTF-16のASCII非互換• 値としてはASCII互換だけど、2バイトに膨らます処理が必要• 2倍の長さの配列を確保して• 値をコピーして…abcáèö61 62 63 E1 E8 F60061 62 63 E1 E8 F600 00 00 00 00Latin-1UTF-16案外高コスト
4バイト文字(追加面文字)• 10000以上の文字(UTF-8でもUTF-16でも4バイト)は…• レア(だった)• 絵文字普及前は本当にめったに使われなかった• 後付け仕様• 元々は2バイト固定のつもりだった• 後付けなので「追加面」(supplementary plains)と呼ばれる• よくバグってた• UTF-16で代用対を受け付けないコードは今でも多い• UTF-8を「最大3バイトの符号化方式」と思って書かれてるコードあり• 「絵文字のおかげで欧米人が4バイト文字に対応してくれた」Unityとかまさに MySQLが5.4まではそうだったらしい
流れの変化• 2000年代半ばを境に流れが変わった• 2バイト固定長にできないのならUTF-16のメリットはあるのか• ASCII互換性の方が大事ではないか(実際大事)• プログラミング言語の文字列の内部形式の変遷:• C#、Java、JavaScriptとかはUTF-16• Go、RustとかはUTF-8これのせいで文字列処理が遅くなったりする※※ C#は最近(.NET Core 3.0で) Utf8クラスを追加してたりする(stringを介さず文字列処理することでパフォーマンス改善)
参考: C#でUTF-8処理• .NET CoreにはUTF-8化の波が来てる• .NET Core 3.0 (去年)で Utf8クラスを追加• .NET 5 (今年末予定)でstringに変わるUtf8Stringクラスを追加予定• たぶんUnityには当面来ないけど…• 自前実装してでもUTF-8処理するとかなり高速化する• 実際自分もやったことあり• https://github.com/ufcpp/Utf8Utils• https://github.com/ufcpp/UnicodeDataCsharp• 最速JSONシリアライザーが速いのはその辺りにも理由あり
UTF-16の「ほとんどの文字が固定長」• 一応、UTF-16は「ほとんどの文字が固定長」• 絵文字の登場頻度もそう高くはない• 4バイトな漢字は極めてレア• 「ほぼ」固定長にはそれなりのメリットあり• 頻度に偏りがある分岐は速い(分岐予測が当たる)• 「何個か先の文字をのぞき見しつつ」みたいな処理を繰り返すなら、UTF-8よりUTF-16の状態の方が速い
代用対の片割れ (incomplete surrogate)• 代用対の片割れは文字として認められるか• 例:• D830が単体で出てきた場合をどうみなすべきか• おおらかだったころ• Unicodeは2バイト固定の文字コードのつもりだった• 「2文字で1文字を代用」と考える• D830は「代用対の片割れ」(の内の上位(high surrogate))の「文字」符号点 1F600UTF-8UTF-16F0, 9F, 98, 80D83D, DE00
代用対の片割れ (incomplete surrogate)• 代用対の片割れは文字として認められるか• 例:• D830が単体で出てきた場合をどうみなすべきか• 今の考え方• D830はあくまでUTF-16符号化の結果として現れるだけ• 有効な符号点ではない• 不正な値はFFFD (replacement character �)に置換すべき符号点 1F600UTF-8UTF-16F0, 9F, 98, 80D83D, DE00セキュリティリスク回避
Unicode Scalar、WTF-8• 「有効な符号点」だけを指す用語が必要になった• 符号点から代用対用のD800~DFFFを除外• 互換性用に「不正なUTF-8」が必要になることがある• D830をUTF-8符号化するとき推奨方式 : FFFD に置き換えた上で符号化して EF, BF, BD互換モード : そのまま疑似的に符号化して ED, A0, BDUnicode Scalarと呼ぶWTF-8 (wobbly transformed format)とかいう仕様があったり(wobbly: グラグラ、不安定)
書記素符号点 ≠ 人が「文字」だと認識する単位どの道「文字」は可変長
符号点/UTF-32なら「固定長」?• 否: Character同士が結合して1文字をなすa(ラテン文字)́(アクセント記号)á か(ひらがな)゙(濁点)が接合文字(絵文字) (絵文字)ᄋ(ハングル字母)ᅡ(ハングル字母)아U+61 U+301 U+304B U+3099U+110B U+1161U+1F469 U+1F469U+200D結合文字(タイ語子音) (タイ語母音)U+0E2D U+0E31字母の組み合わせ㐂(漢字)異字体セレクター㐂󠄁U+3402 U+E0101㐂(漢字)㐂󠄂U+3402 U+E0101(絵文字)U+1F469異字体セレクター(肌トーン)U+1F3FB異字体絵文字(地域指定)U+1F1EFJ(地域指定)U+1F1F5P(地域指定)U+1F1FAU(地域指定)U+1F1F8S例:
結合文字 (combining mark)• 1文字前の文字にくっつく記号がある• ラテン文字の発音区別符号(diacritical mark)とか• 日本語の濁点、半濁点とかa(ラテン文字)́(アクセント記号)áU+61 U+301か(ひらがな)゛(濁点)がU+304B U+3099ちなみに、1文字で「á」を表す符号点もある(E1)同じく、「が」にも符号点がある(304C)
何のための結合文字か• マイナーな組み合わせのための結合文字• か゚ … か + 半濁点 (304B + 309A)• 意識しないと区別がつかないけど、日本語の「が」には鼻濁音 (nga)が混ざる• 放送業界でgaとngaの区別のために半濁点を使ったことがあるらしい• せ゚… せ + 半濁点 (305B + 309A)• アイヌ語の「ちぇ」の音の表記に使われることがあった• 今は普通に「ちぇ」で表記• ら゚… ら + 半濁点 (3089 + 309A)• 外来語の L 音と R 音の区別のために使ってた時期があるらしい• L 音に半濁点こんなマイナー用途に1つの符号点は与えない
書記素• 符号点 ≠ 人が1文字と認識する単位• 人が1文字と認識する単位を書記素 (grapheme)と呼ぶ• (言語学方面でのgraphemeとは用法がちょっと違うみたいなので注意)• 書記素を構成する符号点の塊を書記素クラスター(grapheme cluster)と呼ぶ• カーソル移動、選択、削除はこの単位で行うべき• さもないと家族が1人、また1人と削られていく…どう見ても1文字にしか見えないけど…ZWJ ZWJ ZWJ11個の符号点の塊で構成されてる = 書記素クラスター
書記素クラスター分割• unicode.orgに仕様あり• UAX #29: Unicode Text Segmentation• 昔はシンプルだった• 「letter + combining mark」くらい• 今は結構複雑• 東南アジアに面倒なくっつき方する文字が結構あった• 漢字の異字体選択(後述)とかが仕様に入った• 絵文字のせいでカオス(後述)とりあえず覚えておくべきことは「文字コードというのはどうあがいても可変長」
いろんな文字の落とし穴昔の文字コードの名残があったりいろんな言語にはいろんな背景があったり
世界中の文字を収めるということは…• 世界中の問題をそのまま抱えることに• Unicodeは、いろんな言語のいろんな文字を処理するためのデータもいろいろ提供• UCD (Unicode Character Database)• https://www.unicode.org/Public/UCD/latest/ucd/• ここから先は、いくつかの言語を例に文字の落とし穴的な話を
Latin-1拡張ラテン文字西欧言語の大部分をカバーUnicode符号点のFF以下の部分
Latin-1• ASCIIコードに加えて128文字• 1バイトで西欧の大部分をカバー0 1 2 3 4 5 6 7 8 9 A B C D E F8 PAD HOP BPH NBH IND NEL SSA ESA HTS HTJ VTS PLD PLU RI SS2 SS39 DCS PU1 PU2 STS CCH MW SPA EPA SOS SGCI SCI CSI ST OSC PM APCANBSP¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ SHY® ¯B ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿C À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î ÏD Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ßE à á â ã ä å æ ç è é ê ë ì í î ïF ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ
ASCIIの次に支配的な地位• Unicode符号点の0~FFはLatin-1互換• ただ、UTF-8に符号化すると80以降は互換性なし• 2バイト化する• UTF-8はASCII互換だけどLatin-1互換じゃない• 「西」の人はよく「Latin-1 で十分」とか思ってるので要注意• 「1バイト文字といえばASCIIじゃなくてLatin-1」と思ってる節あり• 「文字コードが不明ならとりあえずLatin-1扱い」みたいなコードよくあった• 文字化けでÀÁÂÃÄÅとかをよく見るのはそのせい
Latin-1の時点で変な文字• ß : 元々はssの合字だけど今はssと使い分けられる• 合字のわりにだいぶ字形が違う• Þ þ : これだけラテン起源じゃなくてルーン文字起源• 多くの言語ではthに転記して消失。アイスランド語とかで現存• ì í î ï: i+発音記号だけど i に元々あるドットが消失• ÿ : フランス語だとy+発音記号、オランダ語だとijの合字
Latin-1にないラテン文字• œ : oeの合字• フランス語でまれに使う• ギリシャ語起源の単語にだけ登場• 起源が違うのでoeとは読みが違う、読みが違うなら別の文字にしたい• æはLatin-1だけどœはLatin-1じゃない• ẞ : ßの大文字• 語頭に立たない文字なので近代まで不要とされてた• 急に必要論が高まって2008年に Unicode にも採用• ı :トルコ語では I の小文字はこれ• i の大文字は İ
漢字Unicodeが2バイトに収まらない最たる元凶利用者は多く、こなれてはいる
Unicodeにおける漢字の境遇• 「非ラテン文字の中ではかな漢字はだいぶこなれてる方」• 利用者が多いから「バグ修正」が進んでるだけ• パッチにパッチを重ねてる状態なのでカオス度は高い「できなくて困る」みたいなのは少ないけど処理が簡単なわけじゃない
同じ意味の別字体• 日本語の漢字と中国語の漢字は同じか• 例えばヨーロッパの言語だと…• A (0041) : ラテン文字のア (エイ)• Α (0380) : ギリシャ文字のアルファ• А (0410) : キリル文字のアー• a (0061) : ラテン文字Aの小文字• a (0061) : ↑と同じ文字。書体違い同源、同字形、同系統の音だけどそれぞれに符号点割り当てありこれだけ字形が違っても同じ文字符号点も同じ
結局どうなったか• Unicode制定時、二転三転したみたい• 字形が違っても同源、同意のものは統合すべきである• 同源、同意で、字体が近いものだけ統合しよう• というか、文字多過ぎてわからねぇ• 結局、全然わからない。雰囲気で決まっている※※ 当然、最大限努力をしたけど無理だった結果なので最初から雰囲気で決めたわけではない日本 簡体字(中国本土) 繁体字(台湾・香港)4E9C 4E9A 4E9E別の符号点が割あたってる6B21 6B21 6B21同じ符号点フォントで字体が違う
フォントを出し分けたいんだけど…• と は文字コード上は完全に同じ文字• 例: https://ja.wikipedia.org/wiki/%E7%B9%81%E4%BD%93%E5%AD%97表示結果:HTMLの内容:<td lang="zh-tw">次</td><td lang="zh-hk">次</td><td lang="zh-cn">次</td><td lang="ko">次</td><td>次</td>マークアップで言語なりフォントなりを明示的に指定しないと無理
自動判定• ある程度の自動判定はできなくもない• 「ひらがなを含んでいたら日本語」みたいな荒い判定• 簡体字でしか使わない符号点、繁体字でしか使わない符号点もある• その手の情報も一応 UCD がデータ提供して…
自動判定• ある程度の自動判定はできなくもない• 「ひらがなを含んでいたら日本語」みたいな荒い判定• 簡体字でしか使わない符号点、繁体字でしか使わない符号点もある• その手の情報も一応 UCD がデータ提供して…
自動判定• ある程度の自動判定はできなくもない• 「ひらがなを含んでいたら日本語」みたいな荒い判定• 簡体字でしか使わない符号点、繁体字でしか使わない符号点もある• その手の情報も一応 UCD がデータ提供して…展開後、合計34MB
日本語だけでも…• 人名漢字は分けざるを得ない• 「紛らわしいからお前今日から斉藤な」とは言えない• 斉、斎、齋、齊、齋、齎• 源流・意味で分けると2つだけ• 斉 … ひとしく。本来の読みは「せい」• 斎 … ものいみ• 異字体全部別の符号点吉5409𠮷20bb7異字体に別の符号点が割あたってる(「つちよし」。吉野家の吉の本来の字体)葛845B葛󠄀845B + E0100符号点は1つ追加で字体選択用の制御文字を付ける(異字体セレクター (variation selector))当たり前のように追加面文字
特に機械的なルールはない• 愚直にテーブルを持つしかない• さきほどの「34MB」から必要な部分を抜き出して使ったり• OSに頼ったり• テーブル化はUTF-16の方が楽だったりする• 利用頻度の多い文字は大半が2バイト固定長• (UTF-8だと1~3バイト)
アラビア文字ラテン文字、漢字に次いで3番目大変
アラビア文字• 利用者は結構多い• アラビア語2億3500万人• ペルシア語7000万人• ウルドゥー語6100万人• その割にすごく大変• 右から左に書く• 隣の文字とつながって字形が変わるインド・ヨーロッパ語族(アラビア語より英語の方が出自が近い)ヒンディー語と相互理解可能文字はアラビア文字聖典を通していろんな言語に幅広く普及今日は時間の都合で「右から左」の方だけ説明
右から左(R to L)アラビア文字ヘブライ文字
論理順と表示順• 論理順• データ上は「読む方向」で文字を並べる• 表示順• 右から左に書く言語だと、当然他の言語と向きが逆例: ‫اللغة‬ (アラビアのアラビア語表記)論理順: ‫ا‬ ‫ل‬ ‫ل‬ ‫غ‬ ‫ة‬ (a, l, l, g, h)表示順: (h, g, l, l, a)‫ا‬‫ل‬‫ل‬‫غ‬‫ة‬
表記• 入力が大変なので、以下の表記で説明• abc... など小文字を L to R (我々にとって普通)の文字• ABC... など大文字を R to L (逆)の文字
R to L仕様• これも unicode.org に仕様書あり• 英語なので、別にアラビア語がわからなくても手を出せる• UAX #9: Unicode Bidirectional Algorithm• 結構長い…• 複雑になる理由が何点かあり• 明示的な向き指定制御文字• L/R 混在• 記号類は周り文字によって向きが変わる• 括弧の対応付け• アラビア文字とヘブライ文字で仕様が違うこれはめったに使わないので今日は省略
L/R混在• アラビア文字の中にあってもラテン文字とかは普通にL to R• 求められる処理のイメージ的には2回ひっくり返す感じ• ちなみにこれを行単位で分けてやる必要あり(先に改行決定が必要)論理順: ABC abc def DEF表示順: FED abc def CBAABC abc def DEFFED fed cba CBAFED abc def CBA どの文字がどの向きかはUCDのBidiPropertyで調べられる
記号類• 記号は周りの文字によって向きが変わる• 記号の両側が同じ向きならその向きにそろえる• 両側が違う向きなら「段落の向き」(先頭文字で決まる)にそろえる論理順: ABC, abc & def, DEF表示順: FED ,abc & def ,CBAdefの右には残らない
括弧の対応付け• 同種の括弧は常に同じ向きでないとダメ• 括弧内に「段落の向き」と同じものがあれば括弧も「段落の向き」• なければ直前の文字の向きABC (abc [ def) DEF( と ) で対応付け中にある [ は浮いてる面倒な処理必須• どの文字が括弧か判定• どの文字とどの文字が対応しているか判定※• 括弧の中身を総なめ※ 対応情報はUCDのBidiBracketsにあり
アラビア文字とヘブライ文字• 数字の後ろの%とかの位置が違う• 口頭でそう読むから (= 論理順がそうだから)• ちなみに1234は「4と30と200と1000」みたいな順で読む(リトルエンディアン)• これのせいで、文字の向きには3カテゴリーある• L : L to R な文字• R : ヘブライ文字• AL : アラビア文字 (% の向き判定のためにRと分かれてる)論理順: ABC 1,234% DEFアラビア文字表示順: FED %1,234 CBAヘブライ文字表示順: FED 1,234% CBA
絵文字それ、文字なん?大体日本のせい
日本には昔から変な文字がある• 日本の印刷業者は変な文字の印刷を受け付けており…• 漢字がすでに複雑なので、ちょっとくらい記号が増えてもよかろう• 文字コード化されてしまう• 当時は「独自拡張」だった• MacJapanese (Shift_JISコードのMac独自拡張)• そしてUnicodeにも引き継がれてしまう〠 〄符号点 3004日本工業規格(JIS)のロゴ(しかも2005年に改訂された古いロゴ)符号点 3020顔郵便マーク(民営化前に郵政省が使っていたマスコット)日本で昔から使っていた「文字」なので、ひらがなの近くに符号点がある
そこに来てケータイキャリア絵文字• カラー液晶搭載機の売りにしたかったのかな…• 文字コード化されてしまう• 当時はキャリアごと(DoCoMo, Softbank, au, ...)に独自仕様• iOS, Androidの日本市場参入に際して標準化 = Unicode 化• Unicodeの文字にいろいろおかしな概念を持ち込む• 文字の定義に色が含まれる(カラー絵文字)• 国とか人種とか、センシティブな話題を踏み抜く• 絵文字シーケンス(書記素の定義が複雑化)1F9E1, 1F499~1F49C1F603, 1F620, 1F61E, 1F616, 1F635
ZWJZWJZWJ1F4681F3FB200D1F4691F3FF200D1F4661F3FD200D1F4661F3FCコードポイント UTF-16D83D DC68D83C DFFB200DD83D DC69D83C DFFF200DD83D DC66D83C DFFD200DD83D DC66D83C DFFCUTF-8F0 9F 91 A8F0 9F 8F BBE2 80 8DF0 9F 91 A9F0 9F 8F BFE2 80 8DF0 9F 91 A6F0 9F 8F BDE2 80 8DF0 9F 91 A6F0 9F 8F BC書記素11文字19文字38バイト41バイト1文字絵文字シーケンスの例1書記素で11符号点UTF-8で41バイトの文字特定の肌色、特定の性別の家族しかないのはおかしい組み合わせ出来るべきだ特にセンシティブな話題として、今日は「国旗」の話を書記素クラスター分割がだいぶ複雑化してる元凶
国旗絵文字の中でも特にセンシティブ「国」にはうかつに触れてはいけない
キャリア絵文字の国旗• むかしむかしとあるキャリアの独自絵文字に国旗がありました• なぜか10か国• 「日本人になじみ深い」以上の基準がない• 人口順でもGDP順でも日本からの渡航者数順でもなんでもなく• 例え基準があったとしてもそれは変化する• というか、国という区切り自体日々変化する
キャリア絵文字のUnicode化• 絵文字を国際規格化したいという段階で困りました• なぜか10か国• 「日本人になじみ深い」以上の基準がないそんなもの国際規格化できるわけないだろう「うちの国がなぜ入ってない?」となる
国名コードを使う• そうだ、国名コードを使おう• 国名コード用にISO 3166-1という規格があるじゃないか• jpとかusとかで国または地域を表す規格= 🇯 (1F1EF) + 🇵 (1F1F5)= 🇺 (1F1FA) +🇸 (1F1F8)• Region Indicator Symbolっていう• 1F1E6~1E1FF までにA~Zに相当する符号点がある• それを2文字並べることで国旗を表す
国または地域• 「国」とは言い切らないのが大事• 国の定義が難しいからWindowsのオプション画面台湾(国名コードtw)台湾とは?• 中華人民共和国の台湾省?• 中華民国?
Windowsでの国旗絵文字• 表示されない• というか、絶対表示させない硬い意志を感じる🇯🇵🇺🇸🇨🇳🇹🇼• つまり、Microsoftは今でも国旗絵文字に反対Region Indicator に対応するラテン文字をそのまま表示(この文字をコピってiOSとかに持っていくと国旗になる)
とある連合王国の1カントリー• 中国台湾省の旗があるのになんでうちの旗はないんだ?と、クレームを入れ始めたのはこいつ1F3F4E0067E0062E0073E0063E0074E007F1F3F4E0067E0062E0077E006CE0073E007F𓄿 + gbsct𓄿 + gbwls1F3F4E0067E0062E0077E006CE0073E007F𓄿 + gbeng7 符号点28バイト(subdivision flag)終端文字が決まってるだけ実はまだ良心的な仕様
まとめ
まとめ• Unicode• 符号点(どの文字にどの番号を振るか)については一択• 符号化(その番号をどういうバイト列にするか)についてはいくつかある• UTF-8が有力なものの、UTF-16もそれなりに使われる• UTF-8, UTF16のバイト数の境目でトラブルを起こしやすい• 西欧の人は文字は1バイトだと思ってる• ごく最近までUTF-8は3バイト以下、UTF-16は2バイト固定扱いされてた• 世界中の文字を収める = 世界中の厄介ごとを引き受ける• 「独自拡張だからいいや」とか言ってると世界標準化される• ローカル規格との互換性 ⇔ 世界中の人が不満なく使える

Recommended

PDF
【Unite Tokyo 2019】Unity Test Runnerを活用して内部品質を向上しよう
PDF
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
PDF
【Unity】 Behavior TreeでAIを作る
PPTX
RPGにおけるイベント駆動型の設計と実装
PDF
コールバックと戦う話
PPTX
DockerコンテナでGitを使う
PDF
Unityでオニオンアーキテクチャ
PDF
Riderはいいぞ!
PDF
【Unite Tokyo 2019】ゼロから始めるアラビア語レンダリング
PDF
【Unite Tokyo 2019】Understanding C# Struct All Things
PDF
中級グラフィックス入門~シャドウマッピング総まとめ~
PDF
こわくない Git
PPTX
【Unity道場Houdini編】Houdini Engine とプロシージャル法
PDF
20分くらいでわかった気分になれるC++20コルーチン
 
PDF
マルチコアを用いた画像処理
PDF
CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編
PDF
Unityでパフォーマンスの良いUIを作る為のTips
PDF
シェーダだけで世界を創る!three.jsによるレイマーチング
PPTX
画像処理ライブラリ OpenCV で 出来ること・出来ないこと
PDF
Pythonによる黒魔術入門
PDF
Observableで非同期処理
PDF
ゲーム開発者のための C++11/C++14
PPTX
世界一わかりやすいClean Architecture
PPTX
なぜなにリアルタイムレンダリング
PDF
UniTask入門
PDF
Twitterのsnowflakeについて
DOCX
UE4でPerforceと連携するための手順
PPT
Glibc malloc internal
PDF
Deflate
 
PPTX
文字コードのお話

More Related Content

PDF
【Unite Tokyo 2019】Unity Test Runnerを活用して内部品質を向上しよう
PDF
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
PDF
【Unity】 Behavior TreeでAIを作る
PPTX
RPGにおけるイベント駆動型の設計と実装
PDF
コールバックと戦う話
PPTX
DockerコンテナでGitを使う
PDF
Unityでオニオンアーキテクチャ
PDF
Riderはいいぞ!
【Unite Tokyo 2019】Unity Test Runnerを活用して内部品質を向上しよう
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
【Unity】 Behavior TreeでAIを作る
RPGにおけるイベント駆動型の設計と実装
コールバックと戦う話
DockerコンテナでGitを使う
Unityでオニオンアーキテクチャ
Riderはいいぞ!

What's hot

PDF
【Unite Tokyo 2019】ゼロから始めるアラビア語レンダリング
PDF
【Unite Tokyo 2019】Understanding C# Struct All Things
PDF
中級グラフィックス入門~シャドウマッピング総まとめ~
PDF
こわくない Git
PPTX
【Unity道場Houdini編】Houdini Engine とプロシージャル法
PDF
20分くらいでわかった気分になれるC++20コルーチン
 
PDF
マルチコアを用いた画像処理
PDF
CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編
PDF
Unityでパフォーマンスの良いUIを作る為のTips
PDF
シェーダだけで世界を創る!three.jsによるレイマーチング
PPTX
画像処理ライブラリ OpenCV で 出来ること・出来ないこと
PDF
Pythonによる黒魔術入門
PDF
Observableで非同期処理
PDF
ゲーム開発者のための C++11/C++14
PPTX
世界一わかりやすいClean Architecture
PPTX
なぜなにリアルタイムレンダリング
PDF
UniTask入門
PDF
Twitterのsnowflakeについて
DOCX
UE4でPerforceと連携するための手順
PPT
Glibc malloc internal
【Unite Tokyo 2019】ゼロから始めるアラビア語レンダリング
【Unite Tokyo 2019】Understanding C# Struct All Things
中級グラフィックス入門~シャドウマッピング総まとめ~
こわくない Git
【Unity道場Houdini編】Houdini Engine とプロシージャル法
20分くらいでわかった気分になれるC++20コルーチン
 
マルチコアを用いた画像処理
CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編
Unityでパフォーマンスの良いUIを作る為のTips
シェーダだけで世界を創る!three.jsによるレイマーチング
画像処理ライブラリ OpenCV で 出来ること・出来ないこと
Pythonによる黒魔術入門
Observableで非同期処理
ゲーム開発者のための C++11/C++14
世界一わかりやすいClean Architecture
なぜなにリアルタイムレンダリング
UniTask入門
Twitterのsnowflakeについて
UE4でPerforceと連携するための手順
Glibc malloc internal

Similar to Unicode文字列処理

PDF
Deflate
 
PPTX
文字コードのお話
PPT
UnicodeによるXSSと SQLインジェクションの可能性
PPTX
文字コード勉強会
PDF
文字コード略歴
PPTX
A Reintroduction To Ruby M17 N
PPTX
文字コード入門 理論編 クイズ付き
PDF
情報の表現~コンピュータでの数値の表現
PDF
Unicodeについて教えてgooでしつこくきいてみたよ♪
PDF
Camomile - OCaml用Unicodeライブラリ
PPTX
JIS2004 with Windows SDK
PDF
文字コードとセキュリティ
PDF
文字コード略歴
PDF
Unicode-v11-0
PDF
Web技術勉強会 第34回
PDF
Rubysapporo Stringsearch
PDF
Unicode 2018 recruit internship
PDF
テキストファイルを読む💪 第1回
PDF
文字コード基礎論A
PPTX
プログラミング言語「A」 2019 07 08
Deflate
 
文字コードのお話
UnicodeによるXSSと SQLインジェクションの可能性
文字コード勉強会
文字コード略歴
A Reintroduction To Ruby M17 N
文字コード入門 理論編 クイズ付き
情報の表現~コンピュータでの数値の表現
Unicodeについて教えてgooでしつこくきいてみたよ♪
Camomile - OCaml用Unicodeライブラリ
JIS2004 with Windows SDK
文字コードとセキュリティ
文字コード略歴
Unicode-v11-0
Web技術勉強会 第34回
Rubysapporo Stringsearch
Unicode 2018 recruit internship
テキストファイルを読む💪 第1回
文字コード基礎論A
プログラミング言語「A」 2019 07 08

More from 信之 岩永

PPTX
C# 8.0 非同期ストリーム
PPTX
C# コンパイラーの書き換え作業の話
PPTX
C# 8.0 null許容参照型
PPTX
Unityで使える C# 6.0~と .NET 4.6
PPTX
async/await のしくみ
PPTX
C# 9.0 / .NET 5.0
PPTX
C#言語機能の作り方
PPTX
Orange Cube 自社フレームワーク 2015/3
PPTX
.NET Compiler Platform
PPTX
C# 7.2 with .NET Core 2.1
PPTX
C# 8.0 Preview in Visual Studio 2019 (16.0)
PPTX
C# design note sep 2014
PPTX
今から始める、Windows 10&新.NETへの移行戦略
PPTX
今から始める、Windows 10&新.NETへの移行戦略
PPTX
.NET Core 2.x 時代の C#
PPTX
Modern .NET
PPTX
YouTube ライブ配信するようになった話
PPTX
Deep Dive C# 6.0
PPTX
Code Contracts in .NET 4
PPTX
それっぽく、適当に
C# 8.0 非同期ストリーム
C# コンパイラーの書き換え作業の話
C# 8.0 null許容参照型
Unityで使える C# 6.0~と .NET 4.6
async/await のしくみ
C# 9.0 / .NET 5.0
C#言語機能の作り方
Orange Cube 自社フレームワーク 2015/3
.NET Compiler Platform
C# 7.2 with .NET Core 2.1
C# 8.0 Preview in Visual Studio 2019 (16.0)
C# design note sep 2014
今から始める、Windows 10&新.NETへの移行戦略
今から始める、Windows 10&新.NETへの移行戦略
.NET Core 2.x 時代の C#
Modern .NET
YouTube ライブ配信するようになった話
Deep Dive C# 6.0
Code Contracts in .NET 4
それっぽく、適当に

Unicode文字列処理

Editor's Notes

  • #15 日本語PowerPoint が U+005C をどうやっても円記号で表示しやがるので、5CのところはU+29F5 (reverse solidus operator、数学記号の逆スラッシュ)で代用してる。Unicode的には(半角の)円記号はU+00A5で、Latin-1の範囲内にある。こっちを使えばいい。
  • #25 PowerPoint、楔形文字を描画できないんだ… (そこだけ画像)ヒエログリフは行けるのに。
  • #61 ウルドゥー語(パキスタン)自体が、インドのイギリスからの独立の際にイスラム教とヒンドゥー教とまとまらなかった結果生まれた国。日本は早々に左書きに変えてよかったねという話ではある。縦書きという闇は残っているものの。
  • #79 https://power-point-design.com/ppt-design/world-map-for-powerpoint/
  • #81 正確には「うちの旗も入れるよう要望を出した」しか言ってないっぽいけども。あと、そんな遠いアジアの話よりは、フランス領マルティニーク島(国名コードMQ)とか近隣諸国の海外県辺りが気に障ったと思われる。

[8]ページ先頭

©2009-2025 Movatter.jp