参照による配列呼び出しを使用するUNIX KSH / BASH(GNU bash 4.2)

参照による配列呼び出しを使用するUNIX KSH / BASH(GNU bash 4.2)

私はUnixシェルスクリプトに初めて触れましたが、私のコードは次のようになります。

  i=0
for var in 'a' 'b' 'c' 'd' 'e'
do
  content[i]=var
  ((i=`expr i+1`))
done
a=10
b=50
c=40
d=90
e=100
Now I wanted to print the local variables contents using array into the function

print_array
{
echo "${content[0]}"
echo "${content[1]}"
echo "${content[2]}"
echo "${content[3]}"
echo "${content[4]}"
} 

私が望む配列の内容は{a、b、c、d、e}で、a、b、c、d、eというローカル変数があり、割り当てられたいくつかの値があります。 Theを使用してこれらのローカルを印刷したいと思います。私は変数配列の名前、配列要素とローカル変数要素の名前が同じで、$とarray_namesをさまざまに組み合わせて参照呼び出しを試みましたが、うまくいきませんでした。

答え1

だからまず間接印刷機能を定義します...

_print() while [ "$#" -ne 0 ]
         do    printf '$%s = %d\n' \
                       "$1" "$(($1))"
               shift
         done

次に、配列を設定して増分します。

arr=( a b c d e ); i=0
for var in "${arr[@]}"
do  : "$(($var=(i+=10)))"
done

したがって、値は$a10と$b20などになります。最後に印刷だけが残りました...

_print "${arr[@]}"

...標準出力として印刷...

$a = 10
$b = 20
$c = 30
$d = 40
$e = 50

$((これはすべて、シェルが数学拡張を処理する方法のために機能します))。デフォルトではevalsです。算術拡張では、シェル最初拡大するどの数学を試す前に、他の効率的なシェル拡張を実行してください。実際の数学を最後の作業にします。

これは次のことを意味します。

i=a a=10; echo "$(($i))" 

印刷された結果は、10シェルが$igetの値を拡張してaからそれを評価するためです。それ結果は整数として参照されます。

上記のコードは、すべてのPOSIX互換シェルで実行できます。

だから私もおそらくそうしたことを意味するでしょう...

i=10
for var in a b c d e
do  arr[($var=i*${#arr[@]}+i)/i]=$var
done

$var[...名前付きシェル配列(これをサポートするシェル内)のインデックス角かっこは、数式の拡張]括弧と同じであるため、配列割り当て、インデックス評価、および整数割り当てを同時に処理します$(())

コマンドに含まれている上記のコードを実行すると、ksh -xc次のデバッグ出力が標準エラーで印刷されます。

+ arr[1]=a
+ arr[2]=b
+ arr[3]=c
+ arr[4]=d
+ arr[5]=e

そこから私はできます:

echo "$((${arr[1]}))"
echo "$((a))"

...印刷...

10
10

これは、名前が指定された配列をサポートするシェルで同じように評価されるためです。しかしいいえ…

echo 'arr=(a b c d e)' | bash -x
+ arr=(a b c d e)     #bash traces the successful command to stderr
echo 'arr=(a b c d e)' | sh -x
sh: 1: Syntax error: "(" unexpected   #sh traces something else

だから_print()関数では私はshift位置引数を入れました。(真のポータブルシェル"$@"配列を表す)何かがありますがprintf...

  1. $まずドル記号があります。
  2. 次に、最初の位置パラメータ%sに文字列値を保存します。$1
  3. =その後は等号があります。
  4. 最後に値を保存します。値は次の場所に保存されます。私の$(($1))最初の位置パラメータです。

関数shiftの引数が消えると、位置引数の数が$#ゼロになり、関数が返されるまで、最初の位置引数は次の位置引数に置き換えられます。

関数を実行する前に配列と間接変数を初期化すると、次のように動作します。

  • for var in "${arr[@]}"

    • [@]シェルは次に展開されます。リストパラメーターと[*]このリストの単一接続。拡張子が参照されない場合可能[*]また、完了時に値があるかどうか、および現在のファイル名拡張子がどのように構成されているかに応じてリストに展開されますが、これを行うと、望む方法で動作しなくなる可能性があります。$IFSset -f
  • : "$(($var=(i+=10)))"

    • の各値は、順番に${arr[@]}その値に割り当てられます。その後、拡張$var$(($var=(i+=10)))最初$varlike の値に対して$((a=(i+=10)))最後にすべての計算を実行します。最初に$i10ずつ増やしてから、値をに割り当て$iます$a

答え2

努力する

#i=0
for var in 'a' 'b' 'c' 'd' 'e'
do
  content[${#content[*]}]=$var  # or content[i++]=$var
done
# or just content=( 'a' 'b' 'c' 'd' 'e' )
a=10
b=50
c=40
d=90
e=100
for i in "${#content[@]}"
do
  echo ${!i}
done

答え3

私が正しく理解したら、変数アクセスへの間接参照が必要ですbash。たとえば、次のコードを使用できます。

content=( a b c d e )

a=10
b=50
c=40
d=90
e=100

echo "${!content[0]}"
echo "${!content[1]}"
echo "${!content[2]}"
echo "${!content[3]}"
echo "${!content[4]}"

あなたは次のようなものを得るでしょう:

10
50
40
90
100

ここで重要なのは、bash具体的な変数拡張アプローチです"${! ... }"

関連情報