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
文字ときどきRuby / Character and Ruby
Search
とみたまさひろ
December 09, 2023
Technology
0
280
文字ときどきRuby / Character and Ruby
とみたまさひろ
December 09, 2023
Tweet
Share
More Decks by とみたまさひろ
See All by とみたまさひろ
私のRSpecの書き方 / How I write RSpec
tmtms
4
1.1k
ショートカットと端末 / shortcut & terminal
tmtms
2
210
文字ときどきRuby / Character and Ruby (NSEG)
tmtms
2
1.4k
Linux用キーリマッパーを作る技術 / How to make Key Remapper
tmtms
0
280
MIMEヘッダエンコーディングは複雑すぎてつらい / MIME header encoding is hard
tmtms
3
1.3k
Net::SMTP
tmtms
1
240
MySQL Parameters の裏側 / MySQL Parameters backend
tmtms
1
380
MySQLユーザ会のこれまでとこれから / MyNA past and future
tmtms
0
67
端末とシグナル / Terminal and Signal
tmtms
2
210
Other Decks in Technology
See All in Technology
Rustで「プリズモイダル法」を利用して「土量計算」をガチでやる
nokonoko1203
1
350
しくじり先生、PharmaXのLLMアプリケーション開発の失敗を語る
pharma_x_tech
0
110
さらばあのボタンとは言わせない SORACOM LTE-M Button powerd by AWSをまだ使えるようにした(前編?)
miura55
0
100
M5stackで使用できるpHセンサの開発
shinrinakamura
1
270
Python と Snowflake はズッ友だょ!~ Snowflake の Python 関連機能をふりかえる ~
__allllllllez__
2
150
コードや知識を組み込む / Incorporate Code and knowledge
ks91
PRO
0
160
DX企業CTOとして考える技術への向き合い方
shoheitai
0
100
生産性向上チームの紹介
cybozuinsideout
PRO
1
960
Babylon.jsと色々なものを組み合わせる:ブラウザのAPIやガジェットや2D描画ライブラリなど / Babylon.js 勉強会 vol.3
you
PRO
0
180
今さら聞けないDocker入門 〜 Dockerfileのベストプラクティス編
devops_vtj
21
6.1k
Gradle Build Scanを使ってビルドのことを知ろう potatotips #87
tomorrowkey
2
160
自らを知り外と繋がる、日経のエンジニア採用とDevRel活動/devreljp92
nishiuma
1
110
Featured
See All Featured
Product Roadmaps are Hard
iamctodd
45
9.8k
How STYLIGHT went responsive
nonsquared
92
4.8k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
275
13k
Code Review Best Practice
trishagee
56
15k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
15
1.6k
Optimizing for Happiness
mojombo
370
69k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
245
20k
The Pragmatic Product Professional
lauravandoore
26
5.8k
Designing the Hi-DPI Web
ddemaree
276
33k
Writing Fast Ruby
sferik
622
60k
Optimising Largest Contentful Paint
csswizardry
13
2.4k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
221
21k
Transcript
文字ときどきRuby nagano.rb #13 2023-12-09 とみたまさひろ 1
自己紹介 • とみたまさひろ • • https://twitter.com/tmtms https://blog.tmtms.net 2
これは同じ文字? 直 直 3
フォントが違うだけで同じ文字 直 U+76F4 日本語フォント 直 U+76F4 中国語フォント 4
これの違いと同じ 直 直 5
コンピュータで扱う文字は文字ごとに番号(コードポイント) が振られていてプログラムから見たときは同じコードポイ ントであれば同じ文字 6
Rubyでコードポイントを知る > '直'.ord.to_s(16) "76f4" > 'ほげ'.chars.map{_1.ord.to_s(16)} ["307b", "3052"] > 'ほげ'.unpack('U*').map{_1.to_s(16)}
["307b", "3052"] 7
これは同じ文字? 令 令 8
違う文字 令 U+4EE4 CJK統合漢字 令 U+F9A8 CJK互換漢字 9
正規化すれば同じ文字 String#unicode_normalize > '令'=='令' false > '令'=='令'.unicode_normalize true 10
正規化でこんなことも 使いようによっては便利 '0'.unicode_normalize(:nfkc) => '0' '①'.unicode_normalize(:nfkc) => '1' 'ア'.unicode_normalize(:nfkc) =>
'ア' 'パ'.unicode_normalize(:nfkc) => 'パ' '㌖'.unicode_normalize(:nfkc) => 'キロメートル' 11
これは同じ文字? 令 � 12
異体字 令 U+4EE4 � U+4EE4 U+E0102 13
基底文字に異体字セレクタを追加することで プレーンテキストでも文字の見た目を 指定することができる 14
異体字セレクタ � U+4EE4 U+E0102 ←これ U+E0100〜U+E01EF が異体字セレクタ 対応システムと対応フォントが必要 15
異体字セレクタ 異体字セレクタセレクタが便利 https://747.github.io/vsselector/#!/ja/908a 16
異体字セレクタ unicode_normalize では消えないので U+E0100〜U+E01EF を消す "\u4ee4\u{e0102}".gsub(/[\u{e0100}-\u{e01ef}]/, '') 17
「髙」と「﨑」 > '高' == '髙' false > '崎' == '﨑'
false 18
「髙」 Unicode では「髙」は「高」の異体字ではなく別の文字 別の文字なので異体字セレクタにもない SJIS(Windows-31J)でも別の文字 でも JIS では「髙」という文字は存在しない 「高」の異体字扱い 19
「髙」 > '髙'.encode('Windows-31J') "\x{FBFC}" > '髙'.encode('SJIS') # SJIS は Windows-31J
の別名 "\x{FBFC}" > '髙'.encode('Shift_JIS') # Shift_JIS と SJIS は異なる # `encode': U+9AD9 from UTF-8 to Shift_JIS # (Encoding::UndefinedConversionError) 20
「髙」 Unicode 上は別の文字なので同一文字として扱わなけれ ばいいんだけど、人名検索とかだと同一文字として扱いた いこともあるかもしれないのでむずかしい 21
「﨑」 CJK互換漢字 「令」と同じ だけど unicode_normalize では「崎」にならない > '﨑'.unicode_normalize "﨑" #
CJK互換漢字は普通は正規化できる > '福'.unicode_normalize "福" 22
「﨑」 これも「髙」と同じく変換するには個別対応が必要そう U+FA11(﨑)はU+5D0E(崎)に統 合漢字ブロックの異体字を持つが、字体 差が大きいとみなされ統合の範疇とされ ていない。 CJK互換漢字 - Wikipedia 23
これは同じ文字? へ ヘ 24
別の文字だけど日本語のバグ へ 平仮名 ヘ 片仮名 25
この文字数は? 26
国旗は2文字 U+1F1EF U+1F1F5 + 国コードを国旗用文字2文字で書くと国旗になる + = 27
3人家族は1文字 U+1F46A 「FAMILY」という絵文字 28
4人家族は7文字 U+1F468 MAN U+200D ゼロ幅接合子 U+1F469 WOMAN U+200D ゼロ幅接合子 U+1F467
GIRL U+200D ゼロ幅接合子 U+1F466 BOY 29
濁点つき文字 ぱ U+3071 ぱ U+306F U+309A 「は」+合成用半濁点文字 (これは unicode_normalize(:nfc) で1文字の「ぱ」になる)
30
囲み文字 a⃝ U+0041 U+20DD a⃤ U+0041 U+20E4 a⃞ U+0041 U+20DE
a ⃣ U+0041 U+20E3 31
人間の肌色と髪型 U+1F9D1(大人) + U+1F3FB(明るい肌色) + U+1F3FC(やや明るい肌色) U+200D U+1F9B0(赤毛) + U+1F3FE(やや濃い肌色)
U+200D U+1F9B2(坊主頭) 32
文字数とは? 33
プログラム的に自然なのは コードポイントの数 でも人にはわかりにくい > ' '.size 10 34
書記素 より 「人が1文字として見える文字」みたいな 書記素(しょきそ、英: grapheme)と は、書記言語において意味上の区別を 可能にする最小の図形単位をいう 書記素 - Wikipedia
35
Ruby で書記素を扱う String#grapheme_clusters > ' '.size 10 > ' '.grapheme_clusters
[" ", " ", " "] > ' '.grapheme_clusters.size 3 36
Ruby で書記素を扱う 正規表現 \X > ' '.scan(/./) [" ", "
", " ", " ", "", " ", "", " ", "", " "] > ' '.scan(/\X/) [" ", " ", " "] 37
まとめ • ユニコードはカオス • 文字列を比較するときは正規化 • 文字数はコードポイントなのか書記素なのかを考える 38