bash 动态(变量)变量名

gia*_*kis 23 bash variable

我想通过操作元素数组并创建一些算术过程来动态创建字符串序列。

for name in FIRST SECOND THIRD FOURTH FIFTH; do
    $name = $(( $6 + 1 ))
    $name = "${$name}q;d"
    echo "${$name}"; printf "\n"
done
Run Code Online (Sandbox Code Playgroud)

期望结果将是下面的$6equals 0

1q;d
2q;d
3q;d
4q;d
5q;d
Run Code Online (Sandbox Code Playgroud)

但我收到这个错误

reel_first_part.sh: line 18: FIRST: command not found
reel_first_part.sh: line 19: ${$name}q;d: bad substitution
reel_first_part.sh: line 18: FIRST: command not found
reel_first_part.sh: line 19: ${$name}q;d: bad substitution
reel_first_part.sh: line 18: FIRST: command not found
reel_first_part.sh: line 19: ${$name}q;d: bad substitution
Run Code Online (Sandbox Code Playgroud)

我想这很简单。当我做类似的事情时它曾经工作过

FIRST=$(( $6 + 1 ))
FIRST="${FIRST}q;d"
Run Code Online (Sandbox Code Playgroud)

Eri*_*ouf 29

如果您想在将名称存储在另一个变量中的同时引用一个 bash 变量,您可以按如下方式进行:

$ var1=hello
$ var2=var1
$ echo ${!var2}
hello
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您将要访问的变量的名称存储在 var2 中。然后使用${!<varable name>}where<variable name>是一个变量来访问它,其中包含要访问的变量的名称。

  • `eval var=\$$holder` 有一种可移植的方式,但是 `eval` 很危险! (3认同)

hee*_*ayl 19

首先,=bash.

要获得您想要的东西,您可以使用eval.

例如像你这样的示例脚本:

#!/bin/bash
i=0
for name in FIRST SECOND THIRD FOURTH FIFTH; do
    eval "$name"="'$(( $i + 1 ))q;d'"
    printf '%s\n' "${!name}"
    i=$(( $i + 1 ))
done
Run Code Online (Sandbox Code Playgroud)

印刷 :

1q;d
2q;d
3q;d
4q;d
5q;d
Run Code Online (Sandbox Code Playgroud)

eval谨慎使用,有些人出于某种正当理由称其为邪恶。

declare 也可以:

#!/bin/bash
i=0
for name in FIRST SECOND THIRD FOURTH FIFTH; do
    declare "$name"="$(( $i + 1 ))q;d"
    printf '%s\n' "${!name}"
    i=$(( $i + 1 ))
done
Run Code Online (Sandbox Code Playgroud)

还打印:

1q;d
2q;d
3q;d
4q;d
5q;d
Run Code Online (Sandbox Code Playgroud)

  • 它称为“bash”参数扩展的间接扩展..阅读[this](http://unix.stackexchange.com/a/41293/68757) (2认同)
  • Bash 还有一个更好的替代 `declare` / `eval` 的方法:`printf -v varname '%fmt' args`。一些 bash 完成内部函数使用它来进行引用调用。(传递要存储的变量的名称)。 (2认同)

Gab*_*les 10

\n

我只是想展示Eric Renouf 的答案的稍微更全面的版本,以清楚地说明如何多个其他变量动态生成变量名称,然后访问该新的动态生成变量的内容。

\n
some_variable="Hey how are you?"\n\n# the 1st half of the variable name "some_variable"\nvar1="some"\n# the 2nd half of the variable name\nvar2="variable"\n\n# dynamically recreate the variable name "some_variable", stored\n# as a string inside variable `var3`\nvar3="${var1}_${var2}"\n
Run Code Online (Sandbox Code Playgroud)\n

现在看看这些输出:

\n
echo "${var3}"\n
Run Code Online (Sandbox Code Playgroud)\n

输出:

\n
\n
some_variable\n
Run Code Online (Sandbox Code Playgroud)\n
\n

但这(与上面完全相同,只是我们!在变量名之前添加了 char ):

\n
echo "${!var3}"\n
Run Code Online (Sandbox Code Playgroud)\n

输出:

\n
\n
Hey how are you?\n
Run Code Online (Sandbox Code Playgroud)\n
\n

太神奇了!

\n

就好像我们有一个 C 宏,其中我们将echo "${${var3}}"其扩展为echo "${some_variable}"然后成为Hey how are you?

\n

但是,该语法无效,并且您会收到以下错误:

\n
$ echo "${${var3}}"\nbash: ${${var3}}: bad substitution\n
Run Code Online (Sandbox Code Playgroud)\n

你可以用这个echo "${!var3}"技巧来代替使用eval,因为eval它被认为是“危险的”和“邪恶的”。不过,为了理解和教育,这里有一个等效的方法来eval代替

\n
$ eval echo "\\$${var3}"\nHey how are you?\n
Run Code Online (Sandbox Code Playgroud)\n

相对:

\n
$ echo "${!var3}"\nHey how are you?\n
Run Code Online (Sandbox Code Playgroud)\n

eval echo "\\$${var3}"展开为eval echo "$some_variable",具有相同的输出:

\n
$ eval echo "$some_variable"\nHey how are you?\n
Run Code Online (Sandbox Code Playgroud)\n

但是,即使 和eval echo "\\$${var3}"在这种情况下echo "${!var3}"产生完全相同的结果Hey how are you?输出),显然eval版本是邪恶的,!版本是好的。

\n

您可以阅读“好”版本(echo "${!var3}"),如下(用我自己的话说):

\n
\n

echoing 的"$var3"意思是:“输出变量的内容var3”。但是,回显"${!var3}"意味着:“输出变量包含的内容var3,假设其内容另一个变量的名称!”

\n
\n

!这里的 bash有点在 C 中用*这样的字符取消引用指针!:

\n
*some_ptr\n
Run Code Online (Sandbox Code Playgroud)\n

它增加了一个额外的抽象层。

\n

有关的

\n
    \n
  1. 请注意,在 bash 中使用关联数组!通常可以避免使用此技巧。关联数组本质上是“哈希表”,在 C++ 中称为“无序映射”,在 Python 中称为“dicts”(字典)。以下是一些相关链接:

    \n
      \n
    1. /sf/ask/430477561/Dimension-associative-arrays-in-bash
    2. \n
    3. [非常好的教程!] ***** https://www.artificialworlds.net/blog/2012/10/17/bash-associative-array-examples/
    4. \n
    \n

    但请记住,bash 中的关联数组(以及所有其他数组)都是一维的!来自man 1 bash(强调):

    \n
    \n

    数组

    \n

    Bash 提供一维索 关联数组变量。任何变量都可以用作索引数组;内置的声明将显式声明一个数组。数组的大小没有最大限制,也没有对成员进行连续索引或指定的要求。索引数组使用整数(包括算术表达式)引用,并且是从零开始的;使用任意字符串引用关联数组。\n除非另有说明,索引数组索引必须是非负整数。

    \n

    如果使用语法\n名称[下标]=值分配任何变量,则会自动创建索引数组。下标被视为必须将 eval\xe2\x80\x90\nuate 转换为数字的算术表达式。要显式声明索引数组,请使用declare -a name(请参阅下面的SHELL\nBUILTIN COMMANDS)。声明 -a name[下标] 也被接受;下标被\忽略。

    \n

    关联数组是使用声明 -A 名称创建的。

    \n

    可以使用声明和只读内置函数为数组变量指定属性。\n每个属性适用于数组的所有成员。

    \n

    数组使用 name=(value1 ... valuen) 形式的复合赋值进行赋值,\n其中每个值的形式为 [下标]=string。索引数组赋值除了字符串之外\n不需要任何东西。当分配给索引数组时,如果提供了可选的括号和\n下标,则该索引将分配给;否则,元素的索引\指定为语句指定的最后一个索引加一。索引从零开始。

    \n

    分配给关联数组时,需要下标。

    \n
    \n
  2. \n
\n