web-dev-qa-db-ja.com

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

比較的簡単だと思いますが、どうすればいいのか分かりません。

#!/usr/bin/ksh
set `iostat`
myvar=6

echo ${$myvar}のように解釈したい${$myvar}-> ${6}-> value

28
Brandon Kreisel

これは、kshを含む多くのファインシェルに組み込まれているevalを使用して実行できます。

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

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

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

30
Bruce Ediger

間接変数参照

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

Mksh≥R39bでは、myvarを名前参照にすることができます。

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を含む古いシェルでは、別の変数名を含む変数があり、この変数の値を使用したい場合にのみ頼むことができますevalBruce Edigerで説明 。このソリューションは、すべてのBourne/POSIXシェルで機能します。

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

配列を使用する

これはここでの最良の方法です。よりシンプルで移植性があります。

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

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

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

set -A a -- "$@"

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

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

Gilles(回答のbashの部分を提供した)が示したように、Bruce Edigerの(evalを使用して移植する方法について)も無効にしないでください。ここにnameref in最近のmksh(およびAT&T ksh93、ただし@Gillesがコメントしたように、namerefsはAT&T kshの定位置パラメーターを参照できず、名前付きパラメーターのみを参照):

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

抵抗を改善するため、setの後に--を追加しました。

1
mirabilos

配列の別の使用法

しばらく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

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

0
Friartek