連結された変数名の逆参照


12

これはできますが、変数の文字列を作成してから参照解除する必要があります。より単純なステートメントに短縮する方法はありますか?

#!/bin/bash

FRUITS="BANANA APPLE ORANGE"

BANANA_COLOUR="Yellow"
APPLE_COLOUR="Green or Red"
ORANGE_COLOUR="Blue"

for fruit in $( echo $FRUITS ); do
    fruit_colour="${fruit}_COLOUR"
    echo $fruit is ${!fruit_colour}
done

私はのようなものをたくさん試してみました${!"${fruit}_COLOUR"}\$${fruit}_COLOURおよび他の多くの変種を、しかし、働いている唯一の方法は、文字列を使用することです。


!構文は、基本的には「二回代理」という変数の置換のフラグです。内部にあるもの${…}が変数名でなければならないという要件は変わりません。そのため、別のメソッド(eval)を使用しない限り、名前を含む変数の使用を避けることはできません。
ジル「SO-悪であるのをやめる」

連想配列を使用して、これをよりきれいに行うこともできます。ただし、質問に対する直接的な回答ではないため、コメントとして追加してください。
パトリック

回答:


10

まず$(echo $FRUITS)forステートメントで使用する必要はありません。使用するだけ $FRUITSで十分です。その後、を使用して、ループ内のいずれかの行を削除できますeval

eval単に二作るためにはbashを告げる評価次の文の(すなわち1以上の通常の評価より)。\$最初の評価を存続$し、次の評価は、この扱い$等「黄色」に解決される変数名、開始、として

この方法では、暫定的な文字列を作成する別の手順を実行する必要はありません(これがあなたの質問の主な意図であると信じています)。

for fruit in $FRUITS ;do
    eval echo $fruit is \$${fruit}_COLOUR
done

別の方法として、パトリックがコメント(上記)で述べたように、代わりに連想配列を使用できます。この場合、要素のインデックスは整数である必要はありません。果物の種類の名前などの文字列を使用できます。次に、bashの連想配列を使用した例を示します。

# This declares an associative array (It unsets it if it already exists)
declare -A colour
colour['BANANA']="Yellow"
colour["APPLE"]="Green or Red"
colour[MARTIAN ORANGE]="Blue"

for fruit in BANANA APPLE "MARTIAN ORANGE" ;do 
    echo "$fruit" is "${colour[$fruit]}"
done

6

これを行うには、bash-builtin evalを使用できます。

#!/bin/bash
FRUITS="BANANA APPLE ORANGE"
BANANA_COLOUR="Yellow"
APPLE_COLOUR="Green or Red"
ORANGE_COLOUR="Blue"

for fruit in $( echo $FRUITS );
do
    fruit_colour=${fruit}_COLOUR
    eval echo $fruit is \$${fruit_colour}
done

バックスラッシュ付きドル記号に注意してください。基本的に、「eval」行はand bash を置換し、次にを呼び出してから2回目の置換を行います。$fruit${fruit_color}evalecho


1

evalステートメントは必要ありません。evalほとんどの言語では、あなたが何か間違ったことをしているというヒントです。

foo_var=10
bar_var=12

# Build a string with your var name of choice
chosen_prefix='foo'
var_name="${chosen_prefix}_var"

# Use bang to deference it
chossen_value=${!var_name}
echo "Chossen value: ${chossen_value}"

eval少なくとも人々が危険で${!var}あることを知っているので、使用する方が安全だと主張しますbash$chosen_prefix攻撃者の制御下にある場合はコマンドインジェクションの脆弱性もあります)。試してくださいvar_name='a[$(uname>&2)0]' bash -c 'v=${!var_name}'。ここでの最善のアプローチは、連想配列です。
ステファンシャゼラス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.