遍历 bash 中的数组列表
Iterating over list of arrays in bash
我需要迭代 bash 中的几个键值数组(关联数组)。这是我的最后一次尝试:
declare -A ARR1
ARR1[foo]=bar
declare -A ARR2
ARR2[foo]=baz
arrays=(ARR1 ARR2)
for idx in "${arrays[@]}"; do
echo ${${idx}[foo]};
done
这当然是错误的(语法错误),但此时此刻,我没有其他想法如何处理它。而在下面的示例中没有错误,但输出只是一个数组的名称。
for idx in "${array[@]}"; do
echo "${idx[foo]}";
done
------- OUTPUT -------
ARR1
ARR2
编辑
好的,我可以使用 eval
:
eval echo ${${idx}[foo]};
但是,我读到在 bash 脚本中使用 eval
并不是一个好主意。有没有更好的办法?
您可以像使用间接替换一样执行此操作,但理想情况下,如果它不是一次性脚本,您不希望使用 bash。
#!/bin/bash
set -ex
declare -A ARR1
ARR1[foo]=bar
declare -A ARR2
ARR2[foo]=baz
arrays=(ARR1 ARR2)
for idx in "${arrays[@]}"; do
x="${idx}[foo]" # Store as a string in a variable
echo ${!x} # Reference using indirection.
done
有关详细信息,请参阅 http://mywiki.wooledge.org/BashFAQ/006。
Bash 4.3-alpha 引入了 nameref attribute,在这种情况下可以使用:
declare -A arr1=([foo]=bar)
declare -A arr2=([foo]=baz)
arrays=(arr1 arr2)
for idx in "${arrays[@]}"; do
declare -n temp="$idx"
echo "${temp[foo]}"
done
给出输出
bar
baz
正如 kojiro 在他的评论中指出的那样,只要名称具有共享前缀,实际上就不需要将数组名称存储在数组中以进行迭代。
arrays=(arr1 arr2)
for idx in "${arrays[@]}"; do
可以替换为
for idx in "${!arr@}"; do
请注意,尽管有感叹号,但这与间接扩展无关。
参考手册的相关摘录
“Shell Parameters”部分:
A variable can be assigned the nameref attribute using the -n
option to the declare
or local
builtin commands (see Bash
Builtins)
to create a nameref, or a reference to another variable. This allows
variables to be manipulated indirectly. Whenever the nameref variable
is referenced or assigned to, the operation is actually performed on
the variable specified by the nameref variable's value. A nameref is
commonly used within shell functions to refer to a variable whose name
is passed as an argument to the function. For instance, if a variable
name is passed to a shell function as its first argument, running
declare -n ref=
inside the function creates a nameref variable ref
whose value is
the variable name passed as the first argument. References and
assignments to ref
are treated as references and assignments to the
variable whose name was passed as </code>.</p>
<p>If the control variable in a <code>for
loop has the nameref attribute, the
list of words can be a list of shell variables, and a name reference
will be established for each word in the list, in turn, when the loop
is executed. Array variables cannot be given the -n
attribute.
However, nameref variables can reference array variables and
subscripted array variables. Namerefs can be unset using the -n
option to the unset
builtin (see Bourne Shell
Builtins).
Otherwise, if unset
is executed with the name of a nameref variable
as an argument, the variable referenced by the nameref variable will
be unset.
“Shell Parameter Expansion”部分:
${!prefix*}
${!prefix@}
Expands to the names of variables whose names begin with prefix
,
separated by the first character of the IFS
special variable. When
@
is used and the expansion appears within double quotes, each
variable name expands to a separate word.
我需要迭代 bash 中的几个键值数组(关联数组)。这是我的最后一次尝试:
declare -A ARR1
ARR1[foo]=bar
declare -A ARR2
ARR2[foo]=baz
arrays=(ARR1 ARR2)
for idx in "${arrays[@]}"; do
echo ${${idx}[foo]};
done
这当然是错误的(语法错误),但此时此刻,我没有其他想法如何处理它。而在下面的示例中没有错误,但输出只是一个数组的名称。
for idx in "${array[@]}"; do
echo "${idx[foo]}";
done
------- OUTPUT -------
ARR1
ARR2
编辑
好的,我可以使用 eval
:
eval echo ${${idx}[foo]};
但是,我读到在 bash 脚本中使用 eval
并不是一个好主意。有没有更好的办法?
您可以像使用间接替换一样执行此操作,但理想情况下,如果它不是一次性脚本,您不希望使用 bash。
#!/bin/bash
set -ex
declare -A ARR1
ARR1[foo]=bar
declare -A ARR2
ARR2[foo]=baz
arrays=(ARR1 ARR2)
for idx in "${arrays[@]}"; do
x="${idx}[foo]" # Store as a string in a variable
echo ${!x} # Reference using indirection.
done
有关详细信息,请参阅 http://mywiki.wooledge.org/BashFAQ/006。
Bash 4.3-alpha 引入了 nameref attribute,在这种情况下可以使用:
declare -A arr1=([foo]=bar)
declare -A arr2=([foo]=baz)
arrays=(arr1 arr2)
for idx in "${arrays[@]}"; do
declare -n temp="$idx"
echo "${temp[foo]}"
done
给出输出
bar
baz
正如 kojiro 在他的评论中指出的那样,只要名称具有共享前缀,实际上就不需要将数组名称存储在数组中以进行迭代。
arrays=(arr1 arr2)
for idx in "${arrays[@]}"; do
可以替换为
for idx in "${!arr@}"; do
请注意,尽管有感叹号,但这与间接扩展无关。
参考手册的相关摘录
“Shell Parameters”部分:
A variable can be assigned the nameref attribute using the
-n
option to thedeclare
orlocal
builtin commands (see Bash Builtins) to create a nameref, or a reference to another variable. This allows variables to be manipulated indirectly. Whenever the nameref variable is referenced or assigned to, the operation is actually performed on the variable specified by the nameref variable's value. A nameref is commonly used within shell functions to refer to a variable whose name is passed as an argument to the function. For instance, if a variable name is passed to a shell function as its first argument, runningdeclare -n ref=
inside the function creates a nameref variable
ref
whose value is the variable name passed as the first argument. References and assignments toref
are treated as references and assignments to the variable whose name was passed as</code>.</p> <p>If the control variable in a <code>for
loop has the nameref attribute, the list of words can be a list of shell variables, and a name reference will be established for each word in the list, in turn, when the loop is executed. Array variables cannot be given the-n
attribute. However, nameref variables can reference array variables and subscripted array variables. Namerefs can be unset using the-n
option to theunset
builtin (see Bourne Shell Builtins). Otherwise, ifunset
is executed with the name of a nameref variable as an argument, the variable referenced by the nameref variable will be unset.
“Shell Parameter Expansion”部分:
${!prefix*}
${!prefix@}Expands to the names of variables whose names begin with
prefix
, separated by the first character of theIFS
special variable. When@
is used and the expansion appears within double quotes, each variable name expands to a separate word.