連想配列を引数リストとしてスクリプトに渡す

連想配列を引数リストとしてスクリプトに渡す

スクリプトには次の連想配列があります。

declare -A VARS=( ["key1"]="value1" ["key2"]="value" )

これを次の形式のパラメータリストに変換できるコマンドはありますか?

--key1=value1 --key2=value2

手動で書き換える必要はありません。

 --key1="${VARS[key1]}" --key2="${VARS[key2]}"

私が念頭に置いているユースケースは、配列をパラメータリストとしてスクリプトに渡すことです。

my_script.sh $(to_param_list $VARS)

@Kusalanandaの答えに対する私の意見を広げるために、正確なユースケースは次のとおりです。 makeselfを使用して自動抽出インストーラを構築するスクリプトがあり、スクリプトにはいくつかの異なるパラメータがあります。

  • スクリプト自体のパラメータ
  • 自動抽出インストーラ内のインストーラパラメータ

その後、スクリプトは次のようにインストーラをビルドします。

to_param_list installer_param_list installer_param_array
./makeself ./path/to/sourcedir ./path/to/created/installer "My installer" ./path/to/install/inside/package "${installer_param_list[@]}"

しかし、パッケージ内で非常に単純なインストーラスクリプトを使用してパラメータ渡しをテストしました。

while ! -z "$1" ; do
    echo "$1"
    shift
done

次の配列を渡します。

installer_param_array=( ["upgrade-from"]="19 .2.0" ["upgrade-to"]="19.3.0" )

結果は次のとおりです。

--upgrade-to=19.3.0
--upgrade-from=19
.2.0

ベストアンサー1

補助機能があります:

#!/bin/bash

to_param_list () {
    declare -n outlist=$1
    declare -n inhash=$2

    for param in "${!inhash[@]}"; do
        outlist+=( "--$param=${inhash[$param]}" )
    done
}

declare -A my_vars=( ["key1"]="value1" ["key2"]="value" )

to_param_list list my_vars
my_script.sh "${list[@]}"

上記のスクリプトの最後のコマンドは書き込みと同じように拡張されます。

my_script.sh "--key2=value" "--key1=value1"

このto_param_list機能は名前配列変数と名前配列変数を連結し、それを使用して関数に2つの「nameref」変数を作成します(namerefはbashバージョン4.3で導入されました)。次に、関連配列の適切な形式のキーと値で指定された配列変数を埋めるために使用されます。

関数のループは、"${!inhash[@]}"連想配列で個別に参照されるキーのリストを繰り返します。

関数呼び出しが返されると、スクリプトは配列を使用して他のスクリプトまたはコマンドを呼び出します。

以下を使用して上記を実行します。

declare -A my_vars=( ["key1"]="hello world" ["key2"]="some thing" ["key3"]="* * *" )

to_param_list list my_vars
printf 'Arg: %s\n' "${list[@]}"

スクリプトが出力されます。

Arg: --key2=some thing
Arg: --key3=* * *
Arg: --key1=hello world

これは、単語分割やファイル名のグロービングが適用されず、オプションが生成されたことを示します。さらに、連想配列からキーにアクセスすることは、かなりランダムな順序で起こるので、キーの順序が維持されない可能性があることを示している。


結果は単一の文字列になるため、ここでは実際にコマンド置換を安全に使用することはできません。引用符なしで置くと、文字列は空白文字(デフォルト)に分割され、それは連想配列のキーと値も分割します。シェルは、結果の単語に対してファイル名のグロービングも行います。二重引用符コマンドの置き換えは役に立ちませんmy_script.sh一つ議論。


あなたの質問についてmakeself:

スクリプトmakeselfはこれを実行するためにインストーラスクリプトの引数を使用します。

SCRIPTARGS="$*"

これにより、パラメータは文字列$SCRIPTARGS(スペースで区切られ、連結)として保存されます。その後、ファイルはそのまま自動解凍アーカイブに挿入されます。オプションを正しく解析するには再評価(これはインストーラを実行するときの場合です。)追加パラメーターを適切に区切るためのパラメーター値内の引用符のセット。

installer_param_array=( ["upgrade-from"]="'19 .2.0'" ["upgrade-to"]="'19.3.0'" )

これは私のコードのバグではありません。makeself生産の副作用だけです。シェルコードユーザーが提供した値に基づいています。

理想的には、makeselfスクリプトが提供されている各パラメータを追加の引用符で囲んで作成する必要がありますが、これは真ではありません。おそらく、これがどのような影響を与えるのかわかりにくいからです。代わりに、ユーザーはこれらの追加の見積もりを提供できます。

上記でテストを再実行しますが、今は

declare -A my_vars=( ["key1"]="'hello world'" ["key2"]="'some value'" ["key3"]="'* * *'" )

to_param_list list my_vars
printf 'Arg: %s\n' "${list[@]}"

生産する

Arg: --key2='some value'
Arg: --key3='* * *'
Arg: --key1='hello world'

あなたは見ることができますこれらいつ文字列再評価シェルではスペースに分割されません。

to_param_list明らかに、最初の連想配列を使用して次を変更することで、関数に引用符を追加できます。

outlist+=( "--$param=${inhash[$param]}" )

入力する

outlist+=( "--$param='${inhash[$param]}'" )

コードに対するこれらの変更の1つはオプション値に一重引用符を含むため、値の再評価は次のとおりです。必要

おすすめ記事