ddスタイルのbashスクリプトにパラメータを渡したいです。基本的に私は欲しい
./script a=1 b=43
同じ効果がある
a=1 b=43 ./script
私は次の方法でこれを達成できると思います。
for arg in "$@"; do
eval "$arg";
done
eval
安全な(つまり、"$arg"
静的一致(コード実行なし))変数の割り当てを確実にするための良い方法は何ですか?
それとももっと良い方法がありますか? (簡単に保ちたかった)。
ベストアンサー1
evalなし(および手動エスケープなし)でbashでこれを行うことができます。
for arg in "$@"; do
if [[ $arg =~ ^[[:alpha:]_][[:alnum:]_]*= ]]; then
declare +i +a +A "$arg"
fi
done
編集する:Stéphane Chazelasのコメントに従って、割り当てられた変数が配列または整数変数として宣言されるのを防ぐために、宣言にフラグを追加しました。これにより、多くの場合、引数の値部分をdeclare
評価しなくなりますkey=val
。 (+a
たとえば、設定した変数が配列変数として宣言されているとエラーが発生します。)これらの脆弱性はすべて、この構文を使用して既存の(配列または整数)変数を再割り当てすることに関連しています。シェル変数として知られています。
実際、これは同じeval
ソリューションに影響を与える注入攻撃クラスの一例にすぎません。既知のパラメータ名のみを許可することは、コマンドラインに表示される変数を盲目的に設定するよりもはるかに優れています。 (PATH
たとえば、コマンドラインで設定した場合は、何が起こるのかを考えてみてくださいPS1
。
私はbash変数を使用するよりも、名前付きパラメータの連想配列を使用することを好みます。これは設定が簡単で安全です。あるいは、実際のbash変数を設定できますが、その名前が有効な引数の連想配列にある場合にのみ可能です。
後者のアプローチの例は次のとおりです。
# Could use this array for default values, too.
declare -A options=([bs]= [if]= [of]=)
for arg in "$@"; do
# Make sure that it is an assignment.
# -v is not an option for many bash versions
if [[ $arg =~ ^[[:alpha:]_][[:alnum:]_]*= &&
${options[${arg%%=*}]+ok} == ok ]]; then
declare "$arg"
# or, to put it into the options array
# options[${arg%%=*}]=${arg#*=}
fi
done