「ポ」と「ポ」は違う文字なのでgrepにヒットしない話
見た目が同じ文字でもgrepにヒットしない場合があるという話
こういう事象になる
$ cat popopo.txt
ポポポポーン1
ポポポポーン2
$ grep "ポ" popopo.txt
ポポポポーン1
$ grep "ポ" popopo.txt
ポポポポーン2
おわかり頂けただろうか…
「ポ」をgrepしてもどちらかしかヒットしない
なぜか…
Unicode結合文字という仕様がある¶
「ポ」と「ポ」は、見た目が同じですが実は違う形式でできているから(Unicodeの仕様)
見た目は同じですが、コンピュータ上では別の文字として扱われます
なので、grepにヒットしない「ポ」がでてきます
「ポ」 と 「ポ」 U+30DD 「ホ」 +「゚」 U+30DB U+309A
これは濁音(「が」とか)と半濁音(「プ」とか)のすべての文字に当てはまります
Unicode正規化という対応方法がある¶
えぇ…じゃぁすごい困るじゃん…検索できないじゃん…
ってなるので、Unicode正規化と呼ばれる統一する方法があります
任意のプログラム言語で実装もできるのですが、ワンライナーでも変換できます
pythonを使ったワンライナー
echo -n "DQⅢ①⑳海海神神㌔㍉ビデブー" | python -c "import sys,unicodedata; print(unicodedata.normalize(\"NFKC\", sys.stdin.read()));" DQIII120海海神神キロミリビデブー
perlを使ったワンライナー
echo -n "DQⅢ①⑳海海神神㌔㍉ビデブー" | perl -e "use strict;use utf8;use Encode;use Unicode::Normalize;binmode STDIN, ':encoding(UTF-8)';binmode STDOUT, ':encoding(UTF-8)';print Unicode::Normalize::NFKC(<STDIN>);" DQIII120海海神神キロミリビデブー
※"DQⅢ①⑳海海神神㌔㍉ビデブー"はテストデータです
では、冒頭の「ポ」で試してみます
$ cat popopo.txt | python -c "import sys,unicodedata; print(unicodedata.normalize(\"NFKC\", sys.stdin.read()));" | grep "ポ" ポポポポーン1 ポポポポーン2
うまくいきました
参考¶
Unicode結合文字 難読化シェル芸
https://www.slideshare.net/kanata1/unicode-112630484
この仕様で遊んでた時の話
文字コードのカオスな世界を整理してみた
https://raintrees.net/news/51
そもそもの文字コードの話
Comments