local:文字化けだけじゃない

投稿者: | 9月 22, 2023

過去に、DeveloperとしてSJIS/EUC/UTF-8の全プラットフォーム対応をしたことがあるのだが、まぁ文字化けだけの問題かというと、それだけではなく、文字のハンドリングもマルチバイト対応をする必要があったりする。ダブルバイトという人もいるが、SJISは1バイトと2バイトの混在だったり、UTF-8に関しては3バイトも使う文字があったりする。単純に最長文字数(日本人はこの議論が大好きだが。)をするときに文字数とするかバイト数とするかで入力ができる文字数が変わってくる。(それを説明して理解してもらうのも大変)

その対応作業中に発生したことで、シェルを使った内部エンジンの動きが言語環境によって異なるという報告がサポートから来た。結局、1行足して直しただけなんだが。その後、膨大にあるその会社の全製品のシェルスクリプトにその1行が足された。LANG=Cという文字列が。

 

という、ロケールって文字化けじゃないよと言っても周りではそんなことないとみんな言うが。。。

 

閑話休題

 

その環境を記憶を辿り再現してみた。環境は、Ubuntu 22.04.3 arm64

 

まずはロケールを知ろう

localeはこんな環境

UntitledImage

蘊蓄だが、en_US.utf-8と書かれているが意味は、

言語_国.文字コードになっている。

一般的には、国と文字コードと認識している人がいるが実は間違いで、カナダだと、英語圏の地域とフランス語圏の地域があるのでロケールが複数ある。

  • en_CA
  • fr_CA

 

1国1言語しかないと思っている人は、これを期に世界をもっとしてみてはと思う。

locale -aで出てくる部分をみると、数字、時間、貨幣単位、紙のサイズなどなど国によって違うので定義を変える必要がある。

つまり、ロケールは単なる文字コードの話ではなく、文化を含んだ話で奥が深い。

さらにロケール

C.UTF-8というのもある。このCというのがある意味便利で、システム標準のロケールとなる。国とかを考えなくてもよくなる。

 

ロケールの変更とテスト

以下のコマンドを打ってみた。微妙に出力が違う。Ubuntuでのロケールの変更は

dpkg-reconfigure localesでインターラクティブに設定することも可能だが、以下のようにコマンドラインでも可能

アメリカ:英語

export LC_ALL=en_US.UTF8
dpkg-reconfigure --frontend noninteractive locales
date

日本:日本語

export LC_ALL=ja_JP.UTF-8
dpkg-reconfigure --frontend noninteractive locales
date

UntitledImage

アメリカは、AM/PMで、日本は24時間制で時間を記載するのですね。初めてしりました。

 

一方LANG=Cは

export LC_ALL=C.UTF-8
dpkg-reconfigure --frontend noninteractive locales
date

UntitledImage

 

次に文字列ソートの話

実は表示の問題だけではなく、ソートの順番もロケールによって異なる。文字列比較とかしていたら結構結果が変わる。

aaaとかbbbという文字列のファイルをA-Zまで大文字小文字で作ってみた。

mkdir test ; cd test
for letter in {a..z} {A..Z}; do
touch "${letter}${letter}${letter}"
done

 

lsコマンドでソートしてみる。なんと順番が違ってくる。

アメリカ:英語

export LC_ALL=en_US.UTF8
dpkg-reconfigure --frontend noninteractive locales
ls -1

UntitledImage

日本:日本語

export LC_ALL=ja_JP.UTF-8
dpkg-reconfigure --frontend noninteractive locales
ls -1

UntitledImage

LANG=C

キャプチャを撮り忘れていたのでこれだけ環境が違う。

export LC_ALL=C.UTF-8
dpkg-reconfigure --frontend noninteractive locales
ls -1

UntitledImage

単純な文字列ソートでもこんなに違う。

余談だが、Windows版のPostgreSQLは、言語環境によってデフォルトのロケールを変えているので、インストールするときにロケールをCにしておかないと、まず動かない。海外物のソフトウェアを使う時は要注意。(多分、ロケールを意識している開発者はいない。誰しも自分のいる環境がデフォルトロケールなので。)

というわけで文字コードに詳しいよっていう人は、単に見聞きしていただけで、それはほんと片鱗だったりする。もちろん適切の文字コードを設定して、マルチバイトの関数を使ってプログラムを作っていればほとんど問題は起きない。

 

ちなみに、文字化けをする理由は、

  • 文字コードの設定とマルチバイトの関数を使っていないか
  • 表示のエンコーディングが間違っている(データはあっているが肝心の表示のエンコーディング設定がおかしい)
  • フォントがない

のこの3つの原因がほとんどだったりする。

コメントを残す