質問の簡単な説明:
配列の完全なコピーを作成したり、配列を使用したりせずに、配列の名前が動的である(つまり、変数に格納されている)bash配列の要素数をカウントする組み込みのbashメソッドはありeval
ますか?
詳しくは:
bashパラメータ置換を使用すると、次のことができます。
- 配列の長さを決定します
myArr=(A B C); echo ${#myArr[@]}
。 - 変数を名前で間接的に参照します
NAME=myVar; echo ${!NAME}
(これは配列要素にも適用されます):
NAME=myArr[1]; echo ${!NAME}
しかし、配列の名前が別の変数に格納されている場合、配列内の要素の数をどのように決定できますか?(これは、上記の2つのパラメーター置換の組み合わせと見なすことができます。)例:
myArr=(A B C D)
NAME=myArr
# Get the number of elements in the array indirectly referenced by NAME.
count=${#$NAME[@]} # This syntax is invalid. What is the right way?
以下は、すべて失敗する複数の試行です。
# Setup for following attempts:
myArr=(A B C D)
NAME=myArr
EXPR1=$NAME[@] # i.e. EXPR1='myArr[@]'
EXPR2=#$NAME[@] # i.e. EXPR2='#myArr[@]'
# Failed attempts to get the lengh of the array indirectly:
1. count=${#$NAME[@]} # ERROR: bash: ...: bad substitution
2. count=${#!EXPR1} # ERROR: bash: !EXPR}: event not found
3. count=${#\!EXPR1} # ERROR: bash: ...: bad substitution
4. count=${!#EXPR1} # ERROR: bash: ...: bad substitution
5. count=${!EXPR2} # Returns NULL
上記の他のいくつかのバリアントも試しましたが、(A)配列のコピーを作成するか、(B)を使用して、以下のいずれかなしで機能するものはまだ見つかりませんeval
。
作業方法:
これを解決するには、おそらく最適ではない方法がいくつかあります(ただし、間違っている場合は修正してください)。
方法1:配列をコピーする
配列を別の(静的な名前の)変数に割り当て、その中の要素の数を取得します。
EXPR=$NAME[@]
arrCopy=( "${!EXPR}" )
count=${#arrCopy}
方法2:使用する eval
EXPR="count=\${#$NAME[@]}" # i.e. 'count=${myArr[@]}'
eval $EXPR
# Now count is set to the length of the array
概要:
間接的に配列の長さを決定するためのbashの組み込みメソッド(つまり、パラメーター置換構文)はありますか?そうでない場合、これを行う最も効率的な方法は何ですか?eval
上記の方法だと思いますが、セキュリティやパフォーマンスの問題はありeval
ますか?
time bash -c 'a=(1 a +); c=a; for ((i=0;i<100000;i++)); do eval "echo \${#$c[@]}"; done' > /dev/null
行いe=$c[@]; d=("${!e}); echo ${#d[@]}
ました:同様に、ループ内でも同様です。評価には、コピーにかかる時間の約90%がかかりました。そして、ギャップは配列とその要素が大きいほど大きくなると思います。