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

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

我确信这相对简单,我只是不知道该怎么做。

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

我想要类似的东西echo ${$myvar},我想将其解释为${$myvar}-> ${6}->value

答案1

您可以使用eval内置于许多优秀 shell 中的 来完成此操作,包括 ksh:

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

技巧是用双引号引用您输入的字符串eval,以便 $myvar 被“6”替换,并反斜杠外部的美元符号,以便eval得到字符串“$6”。

我得到了“%user”的输出,但我在多处理器 RHEL 机器上尝试了它。

答案2

间接变量引用

现代高级 shell 有一种方法来引用名称存储在另一个变量中的变量的值。不幸的是,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}

在较旧的 shell 中,包括 ksh88 和 pdksh,当您有一个包含另一个变量名的变量并且想要使用该变量的值时eval,您唯一的办法是,正如布鲁斯·艾迪格所解释的。该解决方案适用于任何 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]}"

答案3

正如 Gilles(提供了bash部分答案)所指出的,也没有使 Bruce Ediger 的(关于如何使用 进行便携式操作)无效,这是最近eval如何使用(以及 AT&T ksh93,除了 – 正如@Gilles 评论的 – namerefs)不能引用 AT&T ksh 中的位置参数,只能引用命名参数):namerefmksh

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

还添加了--set以提高抵抗力。

答案4

数组的另一种用途

一段时间没有使用 ksh 或任何变体,所以我不确定 ksh(或 bash)是否具有类似的功能。我的主要 shell 是 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

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

相关内容