Bourneに似たデフォルトのシェルを介してコマンドラインで配列サポートをテストするきちんとした方法はありますか?
これは常に可能です。
$ arr=(0 1 2 3);if [ "${arr[2]}" != 2 ];then echo "No array support";fi
または、$SHELL
シェルのバージョンをテストしてください。
$ eval $(echo "$SHELL --version") | grep version
次に、マンページにアクセスできるとし、マンページを読んでください。 (執筆時点でも、/bin/bash
すべてのBourne様シェルは--version
kshが中断したときに長いオプションを認識すると仮定します。例えば.)
私は無人でマージできる簡単なテストを探しています。使用法スクリプトの冒頭では、前のセクションを呼び出すこともできます。
答え1
Bourneのようなシェル(、、、またはcsh
サポートtcsh
配列などの他の多くのシェルrc
)に制限したいのですが、Bourneのようなシェルとも互換性のあるスクリプトを書くのはまったく異なるインタプリタなので、互換性がないので、難しく、しばしば無意味であるとします。 。言語)、実装間に大きな違いがあることに注意してください。es
fish
配列をサポートするBourneに似たシェル(サポートが追加された順序で)は次のとおりです。
ksh88
(元のkshの最後の進化であるksh88は、最初の配列実装であり、ほとんどksh
の伝統的な商用Unicesにまだ存在し、その基盤でもありますsh
。)- 配列は1次元です。
- 配列がorで始まらないと保証できない場合は、配列を
set -A array foo bar
orと定義してください。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
そして派生物(いくつかのBSD、時には複数のBSDの基盤であり、sh
ksh93ソースコードがリリースされるまで唯一のオープンソースksh実装でした):主に好き
ksh88
ですが、注意してください:- 一部の以前の実装ではこれをサポートしていません
set -A array -- foo bar
(--
ここでは必要ありません)。 ${#a[@]}
割り当てられた最大のインデックスに1を加えたインデックス。 (a[1000]=1; echo "${#a[@]}"
配列に要素が1つしかない場合でも、1001が出力されます。- 最新バージョンでは、配列サイズは制限されなくなりました(整数サイズを除く)。
- の最新バージョンには、割り当てられたインデックスのリストを取得するため
mksh
にインスピレーションを受けた追加の演算子、または割り当てbash
laなどの演算子ksh93
があります。zsh
a=(x y)
a+=(z)
${!a[@]}
- 一部の以前の実装ではこれをサポートしていません
zsh
。アレイは一般的に設計が良く、zsh
アレイを最大限に活用します。ご覧のとおりksh
csh
1991年にリリースされたzsh 2.0、デザインインスピレーションはkshではなくtcshから来ます。これはksh
配列といくつかの類似点を共有しますが、重要な違いもあります。ksh
インデックスは、Bourne配列(位置パラメータ$ @、zsh
$argv配列としても公開されています)と配列とcsh
一致して0ではなく1から始まります(シミュレーションを除く)。- 一般/スカラー変数とは異なるタイプです。通常、予想されるように、演算子は異なる方法で適用されます。
$a
配列とは異なり、配列の空${a[0]}
でない要素に展開されます("${a[@]}"
inなどのすべての要素についてksh
)。 - まれな配列ではなく、通常の配列です。
a[5]=1
有効であるが割り当てられていない場合、1〜4のすべての要素は空の文字列として割り当てられます。したがって、${#a[@]}
(kshのインデックス0の要素と同じサイズ${#a}
)は配列内の要素の数です。そして指定された最大インデックスです。 - 連想配列をサポートします。
- 配列操作のための多数の演算子がサポートされており、ここにリストするには多すぎます。
a=(x y)
で定義された配列set -A a x y
との互換性にも使用可能ですksh
が、kshエミュレーションを除いてはサポートされていません(zshエミュレーションでは必要ありません)set -A a -- x y
。--
ksh93
。 (最新バージョンはここで説明されています)。ksh93
原作者が書き直したことは長い間考慮されてきました。ksh
実験的FOSSとしてリリースされて以来、ますます多くのシステムで見つけることができます。たとえば、これは(POSIXシェルがまだベースになっている/bin/sh
Bourneシェルを置き換える)とです。その配列はksh88の配列を拡張して改善します。/usr/xpg4/bin/sh
ksh88
ksh
Solaris 11
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)
スパース配列は構文を使用して一度定義できます。- 最大配列インデックスが4,194,303に増加しました。
- 同じ程度ではありませんが、
zsh
配列で動作する多数の演算子もサポートします。 "${!a[@]}"
配列インデックスのリストを取得します。- 連想配列は別のタイプとしてもサポートされます。
bash
。bash
GNUプロジェクトのシェルです。sh
最新バージョンのOS / 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")
要素を追加または変更する前に、スカラー変数を配列として再定義する必要があります。 "$array"
そのまま配列内のすべての要素に拡張するので、他のシェルよりも使いやすくなります(配列の要素を引数として使用して呼び出されるksh / bash / zshと比較する;オフですが空の要素を削除cmd "$array"
します)。 。cmd
cmd "${array[@]}"
zsh
cmd $array
- として呼び出すと、配列はサポートされません
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
、、、)を使用して配列要素の数(in )をset_array
取得したり、配列を完全に設定したり、単一の要素を割り当てたりできます。set_array_element
$REPLY
おそらく努力する価値はないでしょう。perl
Bourne / 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]}"
ある機能では、ユーザーは通常emulate -L ksh
zshzsh
の方法で配列を使用します。
答え2
以下を使用して配列構文を試すことができますeval
。
is_array_support() (
eval 'a=(1)'
) >/dev/null 2>&1
if is_array_support; then
echo support
else
echo not
fi