他の連想配列に基づいて連想配列を作成する

他の連想配列に基づいて連想配列を作成する

以下のように連想配列を作成しました。いくつかの詳細を提供するために、キーは特定のファイルを参照します。これは大きなスクリプトのコンテキストでこの配列を使用するためです(ファイルを含むディレクトリはgetoptsパラメータになります)。

declare -A BAMREADS
echo "BAMREADS array is initialized"

BAMREADS[../data/file1.bam]=33285268
BAMREADS[../data/file2.bam]=28777698
BAMREADS[../data/file3.bam]=22388955

echo ${BAMREADS[@]}  # Output: 22388955 33285268 28777698
echo ${!BAMREADS[@]} # Output: ../data/file1.bam ../data/file2.bam ../data/file3.bam

これまで、この配列は私が期待したように動作するようです。この配列に基づいて別の連想配列を作成したいと思います。具体的には、2番目の配列は最初の配列と同じキーを持ちますが、$ MINという変数で値を分割したいと思います。

次の戦略のどれが最善かわからないし、どちらも正しく機能しないようです。

戦略1:配列をコピーして配列を変更しますか?

MIN=33285268

declare -A BRAMFRACS
echo "BAMFRACS array is initialized"
BAMFRACS=("${BAMREADS[@]}")

echo ${BAMFRACS[@]}  # Output: 22388955 33285268 28777698
echo ${!BAMFRACS[@]} # Output: 0 1 2

これは私が望む鍵ではありません。動作していても、すべての値について述べた作業を行う必要があります。

戦略2:最初の配列を繰り返しながら2番目の配列を設定します。

MIN=33285268

declare -A BRAMFRACS
echo "BAMFRACS array is initialized"

for i in $(ls $BAMFILES/*bam)
do
    echo $i
    echo ${BAMREADS[$i]}
    BAMFRACS[$i] = ${BAMREADS[$i]} 
done

echo ${BAMFRACS[@]}
echo ${!BAMFRACS[@]}


#When I run this, I get the following error which I am unsure how to solve:

../data/file1.bam
33285268
script.bash: line 108: BAMFRACS[../data/file1.bam]: No such file or directory
../data/file2.bam
28777698
script.bash: line 108: BAMFRACS[../data/file2.bam]: No such file or directory
../data/file3.bam
22388955
script.bash: line 108: BAMFRACS[../data/file3.bam]: No such file or directory

ありがとう

ベストアンサー1

連想配列のコピーに関するより一般的な質問に答えます。

管理者が4.0で独自の連想配列を導入したとき、bashzsh APIの代わりにksh93 APIをコピーするという不幸な決定を下しました。

ksh93/bashは連想配列の設定を完全にサポートしますが、次のものと一致しません。

hash=([k1]=v1 [k2]=v2)

通事論。時間が経つとzshそうです。

hash=(k1 v1 k2 v2)

([k]=v...)ksh93構文のサポートは後で互換性のために追加されました)。

しかし、これはksh93とbashを使用して任意のキーと値のリストからハッシュを生成するのが非常に難しいことを意味します。

zsh構文を使用すると、リストをキーと値を交互に渡すだけです。たとえば、2 つの連想配列をコピーするには、次のようにします。

h2=("${(@kv)h1}")

または2つの列を持つCSVでは:

IFS=$'\n,'; h=($(<file.csv))

またはキーと値の配列から:

h=("${(@)keys:^values}")

ksh93/構文を使用するbashと、キーと値のリスト(たとえば、inなど)に拡張できる"${!h[@]}"andがありますが、目的の構文の(in)キーと値に拡張できる演算子はありません。"${h[@]}""${(@k)h}""${(@v)h}"zsh[key]=valueh=(...)"${(@kv)h}"zsh

ループ内の要素をコピーするのではなく、連想配列をコピーするためにこれらのシェルで使用できる1つの方法はtypeset -p

たとえば、次のようにコピーと同じ操作をzsh実行できます。h2=("${(@kv)h1}")h1h2ksh93bash

h1_definition=$(typeset -p h1) &&
  eval "typeset -A h2=${h1_definition#*=}"

bash次のように短縮できます。

h1_definition=$(typeset -p h1) &&
  typeset -A h2="${h1_definition#*=}"

(ksh93のようにtypeset -A h=valueinの省略形ですが、開始して終了した場合、内容は(参照されているか、一部の拡張の結果であっても)渡されたかのように複合関連付け割り当てとして解釈されます。typeset -A h=([0]=value)bashvalue()eval(

最後に、ループを使用するのも簡単です。

for k in "${!h1[@]}"; do h2[$k]=${h1[$k]}; done

おすすめ記事