在另一个变量“内部”使用变量引用


Answers:


29

您可以使用eval内置到许多精美的shell中(包括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 vv设置为名称在var vn中的var的值,请执行vv=$( eval "echo \$$vn" )。万分感谢!
execNext 2014年

25

间接变量参考

现代高级Shell提供了一种引用变量名称的方法,该变量的名称存储在另一个变量中。不幸的是,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}

在较旧的shell(包括ksh88和pdksh)中,只有拥有包含另一个变量名称的变量并想要使用该变量的值时,这才是唯一的手段eval如Bruce Ediger所述。该解决方案可在任何Bourne / POSIX shell中使用。

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

使用数组

这是最好的方法:更简单,更可移植。

对于您的用例,在任何具有数组的shell中(所有ksh变体,bash≥2.0,zsh),您都可以分配给数组变量并采用所需的元素。注意,ksh和bash数组从0开始编号,但是zsh从1开始编号,除非您发出setopt ksh_arraysemulate 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 2014年

1

正如Gilles(提供bash答案的一部分)所指出的那样,也没有使Bruce Ediger的(使之可移植eval)失效,这是nameref最近的方法mksh(以及AT&T ksh93),除了– @Gilles评论– namerefs不能引用AT&T ksh中的位置参数,只能引用命名参数):

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

也增加了--after功能,set以提高抵抗力。


从ksh 93u开始,namerefs无法引用位置参数(typeset: 6: invalid variable name)。
吉尔(Gilles)'所以

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

我发现较小的块更容易处理。您可能需要也可能不需要使用间接变量引用,具体取决于您的代码。了解其工作原理仍然是一件好事。我自己用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.