web-dev-qa-db-ja.com

スクリプト内からシェルスクリプトの文字エンコーディングを強制する方法

内部に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
5
eadmaster

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の現在の値に従って計算されます。