あなたはボーンのようなシェル(他の多くのシェルが好きに制限したいと仮定するとcsh、tcsh、rc、esまたはfishサポートアレイが、ボーンのようなシェルを同時に互換性のあるスクリプトを書いて、彼らは完全に異なるために通訳されているとして、それらはトリッキーかつ一般的に無意味であると互換性のない言語)、実装間で大きな違いがあることに注意してください。
配列をサポートするBourneのようなシェルは次のとおりです。
ksh88(これは配列を実装する最初の1つです。ksh88はksh、ほとんどの従来の商用Unicesと同じようにまだ見つかりますsh)
- 配列は1次元です
- 配列は、またはで始まらないことを保証できない場合、
set -A array foo barまたはとして定義されset -A array -- "$var" ...ます$var-+。
- 配列のインデックスは
0ます。
- 個々の配列要素はとして割り当てられ
a[1]=valueます。
- 配列はまばらです。これは、設定されていなく
a[5]=fooても機能し、a[0,1,2,3,4]未設定のままにします。
${a[5]}インデックス5の要素にアクセスするには(配列がスパースの場合、必ずしも6番目の要素とは限りません)。5任意の演算式が存在することができます。
- 配列のサイズと添え字は制限されています(4096まで)。
${#a[@]} 配列内の割り当てられた要素の数です(割り当てられた最大のインデックスではありません)。
- 割り当てられた添え字のリストを知る方法はありません(4096要素をで個別にテストする以外
[[ -n "${a[i]+set}" ]])。
$aと同じ${a[0]}です。つまり、配列は、スカラー変数に追加の値を与えることで、なんとかして拡張します。
pdkshと派生物(それはksh、shは、いくつかのBSD BSD ksh93ソースが解放される前の唯一のオープンソースksh実装でした):
ほとんどが好きですksh88が、注意してください:
- いくつかの古い実装がサポートしていませんでした
set -A array -- foo bar(、--そこに必要とされていませんでした)。
${#a[@]}割り当てられた最大のインデックスの1プラスです。(a[1000]=1; echo "${#a[@]}"配列に要素が1つしかない場合でも1001を出力します。
- 新しいバージョンでは、配列サイズが制限されなくなりました(整数のサイズによる以外)。
- 最近のバージョンは、
mkshからインスピレーションを得たいくつかの余分な演算子を持っているbash、ksh93またはzshラの割り当てのようなa=(x y)、a+=(z)、${!a[@]}割り当てられたインデックスのリストを取得します。
zsh。zshアレイは一般に設計が優れておりksh、cshアレイを最大限に活用します。これらは似てkshいますが、大きな違いがあります。
- インデックスは0ではなく1から始まります(
kshエミュレーションを除く)。これはBourne配列(位置パラメーター$ @、これzshは$ argv配列としても公開されcshます)および配列と一致しています。
- それらは通常の/スカラー変数とは別のタイプです。演算子はそれらに別様に適用され、あなたが一般的に期待するように。
$aと同じではありません${a[0]}が、配列の空でない要素に展開さ"${a[@]}"れます(のようなすべての要素に対してksh)。
- これらはスパース配列ではなく、通常の配列です。
a[5]=1機能しますが、割り当てられていない場合は、1から4までのすべての要素に空の文字列を割り当てます。したがって、${#a[@]}(${#a}kshでindice 0の要素のサイズと同じ)は、配列内の要素の数であり、割り当てられた最大のindiceです。
- 連想配列がサポートされています。
- 配列を扱う多数の演算子がサポートされていますが、ここにリストするには大きすぎます。
- として定義され
a=(x y)た配列。set -A a x yも機能しますがset -A a -- x y、kshエミュレーション以外ではサポートされ--ません(zshエミュレーションでは必要ありません)。
ksh93。(ここでは最新バージョンについて説明しています)。ksh93、FOSSとしてリリースされた今、長い間検討されてきた実験的なシステムがますます多くのシステムで見られるようになりました。たとえば、それは/bin/sh(それがBourneシェルに取って代わった場所で/usr/xpg4/bin/shあり、POSIXシェルは依然としてに基づいていますksh88)およびkshof Solaris 11です。その配列はksh88を拡張および強化します。
a=(x y)は配列の定義に使用できますが、a=(...)複合変数(a=(foo=bar bar=baz))の定義にも使用されるため、a=()あいまいであり、配列ではなく複合変数を宣言します。
- 配列は多次元(
a=((0 1) (0 2)))であり、配列要素は複合変数(a=((a b) (c=d d=f)); echo "${a[1].c}")にすることもできます。
- あ
a=([2]=foo [5]=bar)構文は、一度に疎な配列を定義するために使用することができます。
- サイズ制限が解除されました。
- の範囲ではありませんが、
zsh配列を操作するためにサポートされている多数の演算子。
"${!a[@]}" 配列インデックスのリストを取得します。
- 連想配列も別の型としてサポートされています。
bash。bashGNUプロジェクトのシェルです。それは次のように使われているshOS / XおよびいくつかのGNU / Linuxディストリビューションの最新バージョンに。bash配列は主ksh88にksh93およびのいくつかの機能を備えたものをエミュレートしますzsh。
a=(x y)サポートされています。サポートされてset -A a x y いません。a=()空の配列を作成します(には複合変数はありませんbash)。
"${!a[@]}" インデックスのリスト。
a=([foo]=bar)ksh93およびからのいくつかの他の構文と同様にサポートされている構文zsh。
- 最近の
bashバージョンでは、別のタイプとして連想配列もサポートしています。
yash。これは、比較的最近のクリーンでマルチバイト対応のPOSIX sh実装です。広く使用されていません。その配列は、次のようなクリーンなAPIです。zsh
- 配列はスパースではありません
- 配列インデックスは1から始まります
- で定義(および宣言)
a=(var value)
array組み込みで挿入、削除、または変更された要素
array -s a 5 valueその要素が事前に割り当てられていない場合、5 番目の要素を変更することは失敗します。
- 配列内の要素の数は
${a[#]}、${#a[@]}リストのような要素のサイズです。
- 配列は別のタイプです。
a=("$a")要素を追加または変更する前に、スカラー変数を配列として再定義する必要があります。
- として呼び出され
shた場合、配列はサポートされません。
したがって、そこから、配列サポートを検出することがわかります。
if (unset a; set -A a a; eval "a=(a b)"; eval '[ -n "${a[1]}" ]'
) > /dev/null 2>&1
then
array_supported=true
else
array_supported=false
fi
これらの配列を使用するには十分ではありません。ラッパーコマンドを定義して配列全体および個々の要素を割り当てる必要があり、スパース配列を作成しないようにします。
お気に入り
unset a
array_elements() { eval "REPLY=\"\${#$1[@]}\""; }
if (set -A a -- a) 2> /dev/null; then
set -A a -- a b
case ${a[0]}${a[1]} in
--) set_array() { eval "shift; set -A $1"' "$@"'; }
set_array_element() { eval "$1[1+(\$2)]=\$3"; }
first_indice=0;;
a) set_array() { eval "shift; set -A $1"' -- "$@"'; }
set_array_element() { eval "$1[1+(\$2)]=\$3"; }
first_indice=1;;
--a) set_array() { eval "shift; set -A $1"' "$@"'; }
set_array_element() { eval "$1[\$2]=\$3"; }
first_indice=0;;
ab) set_array() { eval "shift; set -A $1"' -- "$@"'; }
set_array_element() { eval "$1[\$2]=\$3"; }
first_indice=0;;
esac
elif (eval 'a[5]=x') 2> /dev/null; then
set_array() { eval "shift; $1=("'"$@")'; }
set_array_element() { eval "$1[\$2]=\$3"; }
first_indice=0
elif (eval 'a=(x) && array -s a 1 y && [ "${a[1]}" = y ]') 2> /dev/null; then
set_array() { eval "shift; $1=("'"$@")'; }
set_array_element() {
eval "
$1=(\${$1+\"\${$1[@]}"'"})
while [ "$(($2))" -ge "${'"$1"'[#]}" ]; do
array -i "$1" "$2" ""
done'
array -s -- "$1" "$((1+$2))" "$3"
}
array_elements() { eval "REPLY=\${$1[#]}"; }
first_indice=1
else
echo >&2 "Array not supported"
fi
そして、あなたは、配列を持つ要素にアクセス"${a[$first_indice+n]}"して、リスト全体を"${a[@]}"ラッパー関数を使用(array_elements、set_array、set_array_element)(の配列の要素数を取得するために$REPLY)、全体またはアサイン個々の要素として配列を設定します。
おそらく努力する価値はありません。perlBourne / POSIXシェル配列を使用または制限します"$@"。
内部的に配列を使用する関数を定義するために、ユーザーの対話型シェルがソースとなるファイルを作成することが目的である場合は、役立ついくつかの注意事項を次に示します。
配列をローカルスコープ(関数または無名関数内)の配列のzshように構成できますksh。
myfunction() {
[ -z "$ZSH_VERSION" ] || setopt localoption ksharrays
# use arrays of indice 0 in this function
}
また、以下を使用してエミュレートすることもできますksh(ksh配列および他のいくつかの領域との互換性を向上させます)。
myfunction() {
[ -z "$ZSH_VERSION" ] || emulate -L ksh
# ksh code more likely to work here
}
このことを念頭に置いて、あなたにしているのサポートを落として喜んでyashやksh88や古いバージョンのpdksh誘導体は、と長いあなたがまばらなアレイを作成しようとしないようとして、あなたは一貫して使用することができるはずです。
a[0]=foo
a=(foo bar)(ではないa=())
"${a[#]}"、"${a[@]}"、"${a[0]}"
ユーザーがまだ自分の配列を通常はzshの方法で使用しているemulate -L ksh間、zsh