1

大きな配列を多くの異なる小さな配列に分割するコードを書こうとしています。最終的に、渡される配列のサイズは不明です。これは私のテスト対象です。私はここまで来ました:

#!/bin/bash
num=(10 3 12 3 4 4)
inArray=${#num[@]}
numArrays=$(($inArray/2))
remain=$(($inArray%2))
echo $numArrays
echo $remain
nun=0
if test $remain -gt  $nun; then
        numArrays=$(($numArrays+1))
fi
array=(1 2)
j=0
for ((i=0;i<$numArrays;i++, j=j+2)); do
        array=("${num[@]:$j:2}")
        echo "The array says: ${array[@]}"
        echo "The size? ${#array[@]}"
done    

私が本当に問題を抱えているのは、変数「配列」の名前を毎回少しずつ変更できるようにしたいので、各配列は保持され、ループ後に一意の名前になります。名前を付けてみましたarray_$iが、次のように返されます。

[Stephanie@~]$ ./tmp.sh 
3
0
./tmp.sh: line 16: syntax error near unexpected token `"${num[@]:$j:2}"'
./tmp.sh: line 16: `    array_$i=("${num[@]:$j:2}")'
[Stephanie@RDT00069 ~]$ ./tmp.sh 
3
0
./tmp.sh: line 16: syntax error near unexpected token `$i'
./tmp.sh: line 16: `    array($i)=("${num[@]:$j:2}")'

誰かアドバイスはありますか?ありがとう

4

3 に答える 3

1

単純な変数では、declareキーワードを使用して間接的な割り当てを行うことができます。

v=foo
declare $v=5
echo $foo    # Prints 5

これは、明白な意味で (とにかく、私には) 配列には拡張されません。

i=2
# This produces a syntax error
declare -a array_$i=("${num[@]:$j:2}")

代わりに、空の配列を宣言できます

declare -a array_$i

またはアイテムを 1 つずつ割り当てます。

declare -a array_$i[0]=item1 array_$i[1]=item2

たとえば、大きな配列の 3 番目と 4 番目の文字を小さな配列にコピーするために for ループを使用する例を次に示します。iより小さい配列の名前の動的部分として、および jその配列へのインデックスとして使用します。

letters=(a b c d e f)
i=1
j=0
for letter in "${letters[@]:2:2}"; do
    # E.g., i=0 and j=1 would result in
    #   declare -a array_0[1]=c
    declare -a array_$i[$j]=$letter
    let j+=1
  done
done

echo ${array_1[@]};  # c d

${foo[@]:x:y}x, x+1, ..., x+y-1からの要素を提供しfoo

全体を別の for ループ内にラップして、letters3 つの小さな配列に分割するという目標を達成できます。

 # We'll create array_0, array_1, and array_2
for i in 0 1 2; do 
  # Just like our subset above, but start at position i*2 instead of
  # a constant.
  for letter in "${letters[@]:$((i*2)):2}"; do
      declare -a array_$i[$j]=$letter
  done
done

3 つの配列にデータを入力できたら、.csv なしでどのようにそれらにアクセスしますevalか? Bash には間接アクセス用の構文があります。

v=foo
foo=5
echo ${!v}   # echoes 5!

感嘆符は、展開するパラメーターの名前として値を使用する必要がある変数として、その後に続く単語を使用することを示しています。それを知っていれば、次のことができると思うかもしれませんが、それは間違いです。

i=1
v=array_$i   # array_1
echo ${!v[0]}  # array_1[0] is c, so prints c, right? Wrong.

上記でbashは、呼び出された変数を見つけてv[0]展開し、展開するパラメーターの名前を取得しようとします。実際には、配列とそのインデックスを 1 つの名前として扱う必要があります。

i=1
v=array_$i[0]
echo ${!v}    # This does print c
于 2012-07-18T19:04:50.447 に答える
1

ここは本当に避けられないと思いますがeval、気をつけていれば安全にできるかもしれません。これが私のアプローチです:

for name in "${!array_*}"; do # Get all names starting with array_
    i="${name#array_*}" # Get the part after array_
    if [[ $i != *[^0-9]* ]]; then # Check that it's a number.
        printf '%s is not a valid subarray name\n' "$name"
    else
        # Create a variable named "statement" that contains code you want to eval.
        printf -v statement 'cur_array=( "${%s[@]}" )' "$name"
        eval "$statement"
        # Do interesting things with $cur_array
    fi
done

$nameこの前に、配列を作成しているときは、どうあるべきかを知っているので、そのprintf -v部分を使用してください。

さらに安全にするために、許可されているすべての配列名を別の配列に保存し、それが memberであることを確認でき$nameます。

于 2012-07-18T19:42:35.703 に答える
0

これは機能するはずですが、これは良い解決策ではありません。別の言語の方が良いかもしれません bash は多次元配列をサポートしていません

eval array_$i='('"${num[@]:$j:2}"')'

そして、例えば

eval 'echo "${array_'$i'[0]}"'
于 2012-07-18T19:11:06.447 に答える