Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
文字とはなにか - PHPの文字コード処理について - PHP Lovers Meetup #5
Search
てきめん tekimen
PRO
March 23, 2024
1
210
文字とはなにか - PHPの文字コード処理について - PHP Lovers Meetup #5
Gina Peter Banyardさんをお迎えして急遽行われたMeetupで発表したスライドです。PHPカンファレンス北海道2024のをちょっと修正を加えたものです。
てきめん tekimen
PRO
March 23, 2024
Tweet
Share
More Decks by てきめん tekimen
See All by てきめん tekimen
Windows版php-srcデバッグ方法
youkidearitai
PRO
1
44
PHP Internals わいわい #1 の資料
youkidearitai
PRO
1
980
mb_trim関数を作りました
youkidearitai
PRO
1
660
PHPの次期バージョンはこの時期どうなっているのか - Internalsの開発体制について - PHPカンファレンス小田原
youkidearitai
PRO
1
460
はじめてのOSSコントリビュート
youkidearitai
PRO
11
3.5k
文字とはなにか - PHPの文字コード処理について -
youkidearitai
PRO
0
660
現在のmbstringの立ち位置 これからどうなっていくのか
youkidearitai
PRO
0
220
PHP 8.3のmbstringの進化を見てください - コントリビューターとしてのかかわり -
youkidearitai
PRO
0
1.2k
PHP 8.2と8.1で取り込まれたプルリクエストについて
youkidearitai
PRO
0
310
Featured
See All Featured
How To Stay Up To Date on Web Technology
chriscoyier
788
250k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
10
720
Bootstrapping a Software Product
garrettdimon
PRO
305
110k
Thoughts on Productivity
jonyablonski
67
4.3k
BBQ
matthewcrist
85
9.3k
Code Reviewing Like a Champion
maltzj
520
39k
Practical Orchestrator
shlominoach
186
10k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
232
17k
Scaling GitHub
holman
458
140k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
28
2k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
44
6.8k
Transcript
文字とはなにか - PHPの文字コード処理について - Ginaさんようこそバージョン
自己紹介 てきめん (tekimen) Yuya Hamada(濱田 侑弥) • https://tekitoh-memdhoi.info • X(twitter):
@youkidearitai • https://github.com/youkidearitai • https://mstdn.jp/tekimen • https://phpc.social/youkidearitai • サイボウズ株式会社に所属してます オレ
まずはじめに mb_ucfirst関数とmb_lcfirst関数がマージされました!
コンピューターで文字を表すの基本 • コンピューターは数値しか扱えません • そこで、とある数値をAなどと紐づけていきました • それが文字コードです • 文字コードに照らし合わせて文字を表示してくれる のがフォントですね
Unicodeがよい • ざっくり言ってしまうとUnicodeはいいぞ • 文字化けから開放してくれたぞ!ってなる • 絵文字も使えるぞ 🎉🎉
Unicodeって何? • 世界中のすべての文字を収録しようというもの – ISO/IEC 10646 という工業規格があって、Unicodeと等 しくなるようになっています • JIS
X 0221が現在の日本の工業規格(JIS)での規格です – Unicodeのバージョンに伴って、収録されていく文字が 増えています
UnicodeとJIS X 0221との関係 Unicode ISO/IEC 10646 JIS X 0221 同期
日本版 ※各仕様書を読んだらこの図になりましたが「プログラマのための文字コード技術入 門」もほぼ同じ図になっていました
Unicodeのバージョンについて • 現在最新版は15.1です。 • 2024年ではUnicode 16.0に むけて作業が進められていま す – http://blog.unicode.org/
2023/11/utc-177-highlig hts.html – alphaがリリースされました
絵文字の存在 • バージョンなんてどうでも良くね?と思いがちです が、実はそうもいかないのです • みなさんはこんなことはありませんか? – 私の推しマークは です、時々違う方がいます。気をつ 🩵
けてくださいなどと呼びかけているアイドルさん – 🙇 と♂♀が分割してた
スマートフォンは絵文字を入力しやすい • スマートフォンならば簡単に絵文字を選んで入力す ることができます • 新しいスマートフォンほど新しい絵文字を入力しやす くなります • その一方で、大切に長くスマートフォンを使っている 人もいます
その結果起こること • Unicodeのバージョンに気を使う必要があります – 古いスマートフォンでは絵文字が見えなかったり、分か れて見えたりします – 新しいスマートフォンでは当たり前のように新しい Unicodeのバージョンの絵文字が使えます
🩵はどうでしょうか • https://emojipedia.org/ja/%E6%B0%B4%E8% 89%B2%E3%81%AE%E3%83%8F%E3%83%BC %E3%83%88 • どうやらUnicode 15.0で入ったようです – 2023年現在の最新バージョンは15.1です
– かなり新しい絵文字です – 古いスマートフォンでは見えないでしょうね…
🙇と♂♀が分割してた • このケースの場合、土下座をしている人と♂や♀の マークが分割して見えることがあります • 対応している機種であれば、「 」、「 」と表示され 🙇♂️ 🙇♀️
ます • いきなりですがPHPでmb_strlenしてみましょう
mb_strlenした結果 • 1文字のハズなのに、4とでましたね – つまり、4つのコードポイントがあるということになります – mb_str_splitもしてみましょう
mb_str_splitした結果 このように、4つのコードポイントに分かれていること がわかりますし、 と♂が別れています 🙇
コードポイントとは • UnicodeでいうコードポイントとはU+1234などと 記す符号位置で、16進数で表します • mbstringではこの単位で測っていきます
コードポイントは? 2コードポイント目がU+200D、4コードポイント目 がU+FE0Fです
それぞれの意味 • U+200Dはゼロ幅接合子などと呼ばれてお り、Zero Width Joinerの略でZWJと言います • U+FE0Fは異体字セレクタと言い、U+FE00から U+FE0Fまでの範囲16文字を使って絵文字のバリ エーションを表現します
• https://www.unicode.org/glossary/#variation _selector
異体字セレクタについて • 漢字でも使われています – Ideographic Variation Sequence(漢字(表意文字)異体 字シーケンス、IVS)と呼ばれています – 範囲はU+E0100からU+E01EFです
– 組み合わせを定義するのがIVS、字形を定義するデータ ベースをIVD(Ideographic Variation Database)といいま す – https://www.unicode.org/reports/tr37/
漢字の異体字セレクタについて • 例えば「邉」 CJK UNIFIED IDEOGRAPH-9089 – https://glyphwiki.org/wiki/u908a-ue0104 – https://747.codeberg.page/vsselector/#!/ja/9089
– 邉 邉󠄀 邉󠄁 邉󠄂 邉󠄃 邉󠄄 邉󠄅 邉󠄆 邉󠄈 邉󠄉 邉󠄊 邉󠄋 邉󠄌 邉󠄍 邉󠄎 … • 游ゴシック体で表示させました • すべて違う異体字です • 同じ漢字に見えるのもあれば違うのもありますね
絵文字に戻っておさらいしましょう
mb_str_splitした結果 見えないほうはそのようにちがうわけですね ゼロ幅接合子 (ZWJ) U+200D (絵文字の)異体字セレクタ U+FE0F
どうすれば1文字として測れますか?
ICUというライブラリを使います • Grapheme cluster(グラフィム、書記素クラスター)単位で測れば 良い – それを格納しているのがICU – 結局データベースから測らないといけないのです •
PHPではintl拡張に入っています – --enable-intlとしてコンパイルしましょう – grapheme_strlenを使えば測れます • https://www.php.net/grapheme_strlen
PCRE(preg系関数)も使えます • PCREも書記素クラス ター単位での検出がで きます • \Xを使用します • https://www.pcre.or g/original/doc/html/
pcrepattern.html
grapheme_strlenした結果 このようにして、書記素クラスターを正しく数えるこ とができるわけですね
濁音・半濁音の場合
本来の濁音と半濁音 • JIS X 0201ではガのように文字と濁音が別々(いわゆる半角カ ナ) • JIS X 0208ではガのように、独立した文字も収録された
• Unicodeでは独立した文字も別にできたりする – ガが果たしてU+30ACなのか、U+30ABとU+3099の両方なのかが一見 するとわからない – それを統一するのが「正規化」と呼ばれる
正規化の方法 • 正規化方式D(NFD) – $ sapi/cli/php -r 'var_dump(Normalizer::normalize("ガ", Normalizer::NFD));' string(6)
"ガ" # カと濁音が分割されている • 正規化方式C(NFC) – $ sapi/cli/php -r 'var_dump(Normalizer::normalize("ガ", Normalizer::NFC));' string(3) "ガ" • 正規化方式KD(NFKD) – $ sapi/cli/php -r 'var_dump(Normalizer::normalize("ガ", Normalizer::NFKD));' string(6) "ガ" # カと濁音が分割されている • 正規化方式KC(NFKC) – $ sapi/cli/php -r 'var_dump(Normalizer::normalize("ガ", Normalizer::NFKC));' string(3) "ガ" • PHPではintlの Normalizerクラスを使 います • 正規化方式も4種あるの でその時適切な正規化 方式を選択する必要が あります
正規化で戸惑う例 • 例えばハングルの「アニョハセ ヨ」(こんにちは)を正規化 D(NFD)をすると、ハングルの 音節がバラバラに分解されて しまいます(ちゃんと表示できる 場合もありますが) • 参考:
https://www.unicode.org/c harts/normalization/ \
まとめ • Unicodeにはバージョンがあることがわかりました • バージョンによって絵文字が表示されないことがわかりました • ZWJ、異体字セレクタなどで必ずしも1コードポイントに収まらないことがわかりました • 濁音・半濁音は色々な方法の組み合わせがあることがわかりました •
PHPのUnicodeの対応具合がわかりました – mbstringでは1コードポイントごと、intlとPCREでは書記素クラスターとして測れる • 正規化は複雑すぎる、触れないでおければ幸せ • Unicodeは知ることが多いことがわかり、わからないことがわかりました – たとえば、不正なバイトシーケンスとか喋ってないですね? – あなたが知っていることがあったら、教えてください!
提案 • PHPのGrapheme関数には、文字列の処理関数が少ないように見 えます • 少なくとも、mb_str_split相当の書記素クラスターごとにarrayで返 却できるとarray関数で処理できてよいのではと思いますがどうで しょう? • つまり、grapheme_str_splitが必要なのではないかということです
– 絵文字などを「一文字」として配列として分割するというものです – RFCを作りました https://wiki.php.net/rfc/grapheme_str_split
参照 • http://www.unicode.org/L2/L2016/16181-gender-zwj-sequences.pdf • https://ja.wikipedia.org/wiki/%E3%82%BC%E3%83%AD%E5%B9%85%E6%8E%A5 %E5%90%88%E5%AD%90 • https://www.unicode.org/glossary/#variation_selector • https://www.unicode.org/glossary/#ideographic_variation_sequence
• https://www.unicode.org/reports/tr37/ • https://ja.wikipedia.org/wiki/%E7%95%B0%E4%BD%93%E5%AD%97%E3%82%B B%E3%83%AC%E3%82%AF%E3%82%BF#%E7%A8%AE%E9%A1%9E • https://emojipedia.org/ja/emoji-15.0 • https://747.codeberg.page/vsselector/#!/ja/9089 • https://glyphwiki.org/wiki/u908a-ue0104 • https://www.php.net/grapheme_strlen