連想配列をシェルスクリプトに実装するトリックを見ました。たとえば、key = apples print array["apples"]
としてスクリプト化できますecho \$array$key
。
ただし、配列を反復処理するためのキーを生成する方法については言及されていません。スペースで区切られた変数にキーを格納して、forループを使用して配列を反復できるようにすることしか考えられませんでした。
それで、後で使用するためにキーを格納する他の方法はありますか?
連想配列をシェルスクリプトに実装するトリックを見ました。たとえば、key = apples print array["apples"]
としてスクリプト化できますecho \$array$key
。
ただし、配列を反復処理するためのキーを生成する方法については言及されていません。スペースで区切られた変数にキーを格納して、forループを使用して配列を反復できるようにすることしか考えられませんでした。
それで、後で使用するためにキーを格納する他の方法はありますか?
回答:
最近のシェルの中には、連想配列を提供するものがあります:ksh93、bash≥4、zsh。ksh93とbashでは、a
が連想配列の場合、"${!a[@]}"
はそのキーの配列です。
for k in "${!a[@]}"; do
echo "$k -> ${a[$k]}"
done
zshでは、その構文はkshエミュレーションモードでのみ機能します。それ以外の場合は、zshのネイティブ構文を使用する必要があります。
for k in "${(@k)a}"; do
echo "$k -> $a[$k]"
done
${(k)a}
にa
空のキーがない場合にも機能します。
zshでは、k
eyとv
aluesの両方を同時にループすることもできます。
for k v ("${(@kv)a}") echo "$k -> $v"
連想配列を持たないシェルで連想配列をエミュレートすることは、はるかに多くの作業です。連想配列が必要な場合は、ksh93やPerlなどのより大きなツールを導入するときがきました。
単なるPOSIXシェルで連想配列が必要な場合は、キーが文字0-9A-Z_a-z
(ASCII数字、文字、アンダースコア)のみを含むように制限されている場合に、それらをシミュレートする方法を次に示します。この仮定の下で、キーは変数名の一部として使用できます。以下の関数は、2つの連続するアンダースコアを含んではならない「stem」という名前の接頭辞で識別される配列に作用します。
## ainit STEM
## Declare an empty associative array named STEM.
ainit () {
eval "__aa__${1}=' '"
}
## akeys STEM
## List the keys in the associatve array named STEM.
akeys () {
eval "echo \"\$__aa__${1}\""
}
## aget STEM KEY VAR
## Set VAR to the value of KEY in the associative array named STEM.
## If KEY is not present, unset VAR.
aget () {
eval "unset $3
case \$__aa__${1} in
*\" $2 \"*) $3=\$__aa__${1}__$2;;
esac"
}
## aset STEM KEY VALUE
## Set KEY to VALUE in the associative array named STEM.
aset () {
eval "__aa__${1}__${2}=\$3
case \$__aa__${1} in
*\" $2 \"*) :;;
*) __aa__${1}=\"\${__aa__${1}}$2 \";;
esac"
}
## aunset STEM KEY
## Remove KEY from the associative array named STEM.
aunset () {
eval "unset __aa__${1}__${2}
case \$__aa__${1} in
*\" $2 \"*) __aa__${1}=\"\${__aa__${1}%%* $2 } \${__aa__${1}#* $2 }\";;
esac"
}
(警告、テストされていないコード。構文的に無効なステムおよびキーのエラー検出は提供されていません。)
ストアの意味がわかりませんが、次の${!array[@]}
構文を使用してキーを反復できます。
$ typeset -A foo=([key1]=bar [key2]=baz);
$ echo "${!foo[@]}"
key2 key1
したがって、反復するには:
$ for key in "${!foo[@]}"; do echo "$key : ${foo[$key]}"; done
key2 : baz
key1 : bar
私はここにこれについての良い、短いチュートリアルを見つけました。
以下のコメントで指摘されているように、連想配列はbash
バージョン4で追加されました。この件に関するLinuxジャーナルの記事については、こちらを参照してください。
(bash version 4 only)
これは重要なことです。従来、bash
配列は数値のみです。
typeset
代わりに使用したい場合がdeclare
あります。それはそれらを最初にシェル連想配列を実装したbash 4とksh93の間で移植可能にするでしょう。
これはbashで動作します
cert="first"
web="second"
declare -A assoc_array=(["cert"]="${cert}" ["web"]="${web}")
echo "first is" ${assoc_array[cert]}
echo "second is" ${assoc_array[web]}
または
#loop
for i in "${assoc_array[@]}"
do
echo "$i"
done
eval afaikを使用する必要はありません