動かざることバグの如し

近づきたいよ 君の理想に

Ubuntuでマルチバイト文字の文字数を確認する際には注意が必要

環境

問題

以下のうち、正常に文字列(5)が取得できるのは次のうちどれか。

echo -n あいうえお | awk '{ print length($0) }'
echo -n あいうえお | LC_ALL=ja_JP.UTF-8 awk '{ print length($0) }'
echo -n あいうえお | gawk '{ print length($0) }'
echo -n あいうえお | LC_ALL=ja_JP.UTF-8 gawk '{ print length($0) }'

正解は

# bash test.sh 
15
5
15
5

となり、 LC_ALL=ja_JP.UTF-8 とLANGにjaがセットされていれば正常にマルチバイトでも文字数が取れる。逆に言えばセットされてないとバイト数を返してしまう。

原因

awkgawkで文字列の長さを計測する際、デフォルトでは文字単位ではなくバイト単位で長さを返す。特にデフォルトのロケール設定がCやPOSIXの場合、マルチバイトである日本語も1文字を1バイトとしてカウントする。そのため、LC_ALLやLANG環境変数をja_JP.UTF-8に設定することで、マルチバイト文字を正確に1文字として認識させる必要がある。

注意点

1. language-pack-jaが必要

以下のようにして language-pack-ja をインストールしておく必要がある。

RUN apt-get update && \
    apt-get install -y language-pack-ja && \
    rm -rf /var/lib/apt/lists/*

2. 古いUbuntuではロケールを変えてもバグる

Ubuntu 22.04までは、この対応が反映されていないのかlanguage-pack-jaを入れてロケールセットしても文字数を正確に取得できない

echo -n あいうえお | LC_ALL=ja_JP.UTF-8 awk '{ print length($0) }'
15

解決策として、gawkコマンドでは正常に取得できるのでそっちを使う。

参考リンク