内部にUTF8でエンコードされた文字を含むいくつかのシェルスクリプトがあり、マシンのロケール設定に関係なく、それらが正しくデコードされることを確認したいと思います。
シェル(bashまたはsh)に正しいスクリプトエンコーディングを強制的に検出させることは可能ですか? ( pythonまたはRubyエンコーディングCookie に類似したもの)
解決策は、次のようなカスタムのシバンです。
#!/bin/bash --utf8
このソリューションは移植性の向上を目的としているため、bashを使用する必要はありません。
編集:多分私は再帰的なスクリプト呼び出しを使用して可能な解決策を見つけました:
# check if current locale is UTF8-based (otherwise this script may not work correctly)
locale | grep -q 'UTF-8'
if [ $? -ne 0 ]; then
export LC_ALL=en_GB.UTF-8
# recursive call this script with the modified environment
$0 "$@"
exit $?
fi
Bashは文字列をバイト文字列として保存し、現在のLC_CTYPE
設定に従って操作を実行します。したがって、bashを再起動する必要はありません。LC_CTYPE
またはLC_ALL
変数を目的のロケールに設定するだけです。変数または関数に文字列を格納する場合、問題となるのは、変数が展開されたとき、または関数の関連コマンドが実行されたときのエンコーディングです。これを示すスクリプトは次のとおりです。
#!/bin/bash
LC_CTYPE=en_US.utf8
v_utf8='é'
n_utf8=${#v_utf8}
f_utf8 () { tmp='é'; echo ${#tmp}; }
echo "UTF-8 in UTF-8: $n_utf8 $(f_utf8)"
LC_CTYPE=en_US
v_latin1='é'
n_latin1=${#v_latin1}
f_latin1 () { tmp='é'; echo ${#tmp}; }
echo "Latin 1 in Latin 1: $n_latin1 $(f_latin1)"
echo "UTF-8 in Latin 1: ${#v_utf8} $(f_utf8)"
LC_CTYPE=en_US.utf8
echo "Latin 1 in UTF-8: ${#v_latin1} $(f_latin1)"
出力:
UTF-8 in UTF-8: 1 1
Latin 1 in Latin 1: 2 2
UTF-8 in Latin 1: 2 2
Latin 1 in UTF-8: 1 1
ご覧のように、文字列の長さは、定義時の値に関係なく、LC_CTYPE
の現在の値に従って計算されます。