別の変数の「内部」で変数参照を使用する


回答:


29

これを行うにはeval、kshを含む多くの優れたシェルに組み込まれています。

#!/usr/bin/ksh
set $(iostat)
myvar=6
eval "echo \${$myvar}"

トリックはeval、$ myvarが「6」で置換されるように、フィードする文字列を二重引用符で囲み、外側のドル記号をバックスラッシュしevalて、文字列「$ 6」を取得することです。

出力に「%user」を取得しましたが、マルチプロセッサRHELマシンで試しました。


3
あなたは公式にOpenBSD 5.4の計り知れないほどひどいksh(本当にpdksh)でさえ動作する週最高の高貴なグランドマスターです。名前がvar vnにあるvarの値にvar vvを設定する場合は、単に実行します。トンありがとう!vv=$( eval "echo \$$vn" )
execNext 14

25

間接変数参照

最近の高度なシェルには、名前が別の変数に保存されている変数の値を参照する方法があります。残念ながら、この方法はksh、bash、zshで異なります。

mksh≥R39bではmyvar、nameref を作成できます。

typeset -n myvar=6
echo "$myvar"

これは、位置パラメータへの名前参照をサポートしていないため、ATT ksh93では機能しません。変数名を含む変数がある場合、このメソッドを使用できます。

foo=bar
typeset -n myvar=foo
echo "$myvar"  # prints bar

bash≥2.0では、次のように記述できます

echo "${!myvar}"

zshでは、次のように書くことができます

echo ${(P)myvar}

ksh88やpdkshを含む古いシェルでは、ブルース・エディガーが説明したように、別の変数名を含む変数がありeval、この変数の値を使用したい場合にのみ頼りにします。このソリューションは、Bourne / POSIXシェルで機能します。

eval "value=\${$myvar}"
echo "$value"

配列を使用する

これがここでの最良の方法です。より簡単で移植性があります。

ユースケースでは、配列(すべてのkshバリアント、bash≥2.0、zsh)を使用するシェルで、配列変数に割り当てて、希望する要素を取得できます。kshおよびbash配列は0から番号付けを開始しますが、setopt ksh_arraysまたはを発行しない限り、zshは1から開始することに注意してくださいemulate ksh

set -A iostat -- $(iostat)
echo "${iostat[5]}"

位置パラメータを配列変数にコピーする場合a

set -A a -- "$@"

ksh93、mksh≥R39b、bash≥2.0、およびzshでは、配列割り当て構文を使用できます。

iostat=($(iostat))
echo "${iostat[5]}"

うわー、あなたの 'Bourne / POSIX'ソリューションはOpenBSD 5.4のksh / pdkshでも動作します。上記のBruce Edigerの答えに対する私のコメントの例に適用するには、単にを実行しますeval "vv=\${$vn}"。メルシー・ボークー、親切な先生。
execNext 14

1

Gilles(bash答えの一部を提供した)が示したように、ブルース・エディガーの(移植性evalのある方法で)を無効にしないでnameref、最近mksh(およびAT&T ksh93で-@Gillesがコメントしたように-namerefsを除いて) AT&T kshの定位置パラメーターを参照することはできません。名前付きパラメーターのみを参照してください)。

#!/bin/mksh
set -- $(iostat)
nameref myvar=6
echo $myvar

抵抗を改善するために--afterも追加しましたset


ksh 93uの時点では、namerefは位置パラメータ(typeset: 6: invalid variable name)を参照できません。
ジル 'SO-悪であるのをやめる'

0

配列の別の用途

しばらくの間、kshまたはそのバリアントを使用していないため、ksh(またはbash)に同様の機能があるかどうかはわかりません。私の主なシェルはzshです。iostatなどのコマンドからの出力を処理するときは、複数の行を生成し、すべての行が同じ形式/長さではないため、配列を使用します。

#! /bin/zsh
IOStatOutput=("${(@f)$(iostat)}") # Produces one element per line

上記も位置パラメータの使用をバイパスします。ここで、たとえばデバイスの配列を生成する場合:

for Element in {7..${#IOStatOutput}} # Devices listed in elements 7 thru the last
do
    DevList+=( ${${=IOStatOutput[Element]}[1]} )
done

小さいチャンクの方がはるかに扱いやすいと思います。コードに応じて、間接変数参照を使用する必要がある場合としない場合があります。それがどのように機能するかを知ることは、まだ良いことです。自分で使います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.