連想配列のエスケープ文字列 (bash)

連想配列のエスケープ文字列 (bash)

パラメーターを使用して複数のプロシージャーを実行するスクリプトを作成しています。できるだけ簡単にするには、次の例を検討してください。

programs=( "ls" "echo" )
declare -A parameters
parameters["ls"]="-l /tmp/foo"
parameters["echo"]="Hello"

for program in "${programs[@]}"
do
  $program ${parameters[$program]}
done

この方法は、パラメータにスペースがない場合にうまく機能します。もちろん、文字列エスケープは以前に議論されたので、StackExchangeと他のページで見つけることができるさまざまな方法を試しました。ただし、連想配列を使用している場合は、適切な解決策が見つかりません。たとえば、「/tmp/foo bar」リストを取得するには、次のいずれも必要ありません。

parameters["ls"]="-l /tmp/foo bar"

これでもありません。

parameters["ls"]="-l \"/tmp/foo bar\""

これでもありません。

parameters["ls"]="-l /tmp/foo\ bar"

期待どおりに動作します。同様に、ループのプログラム呼び出しの周りに引用符を入れます。

  $program "${parameters[$program]}"

また、2つの引数(-lとpath)が1つの引数として解釈されるため、機能しません。

私が見つけた最も近い解決策この投稿プログラム呼び出しでは、パラメータごとに1つずつ複数の個別変数を使用することをお勧めします。ただし、私のユースケースでは、各プログラムに可変数のパラメータが必要なため、これは不可能です。だから、連想配列を使用します。

パス名を脱出する別の方法はありますか?

アンドレアス安否挨拶

ベストアンサー1

まず、パラメータを含む配列を作成します。

次に、配列文字列値を見つけて保存し、declare -pそれparametersを復元して、次のように実際の配列として使用します。

#!/bin/bash

programs=( "ls" "echo" )
declare -A parameters

arrayTmp=("-l" "/tmp/foo bar")
parameters["ls"]="`declare -p arrayTmp |sed -r "s,[^=]*='(.*)'$,\1,"`"

parameters["echo"]="Hello"

for program in "${programs[@]}";do
    echo "PROGRAM: $program"
    declare -a arrayTmp="${parameters[$program]}"
    $program "${arrayTmp[@]}"
    arrayTmp=()
done

おすすめ記事