我的环境可以具有使用以下格式定义的灵活数量的变量:
Var1Value=A
Var2Value=B
Var3Value=C
我现在想迭代变量,只要它们存在。在伪代码中:
i=1
while [exists "Var"$i"Value"]; do
echo "found variable, now doing some more complex processing logic"
#do some more stuff
i=$((i + 1))
done
我可以在 bash 中完成这项工作(不使用数组)吗?
答案1
用一个名称引用。它们的工作方式有点像指向其他变量的指针(在 Bash 4.3 及更高版本中):
Var1Value=A
Var2Value=B
Var3Value=C
Var4Value=""
for (( i=1 ; ; i++ )); do
n="Var${i}Value" # the name of var
declare -n p="$n" # reference to the var
[ "${p+x}" ] || break # see if it exists
echo "$n: '$p'"
done
"${p+x}"
评估x
是否存在指向的变量p
,因此这也处理设置但为空的变量。
或者,使用间接变量扩展${!n}
,它引用 命名的变量n
。
for (( i=1 ; ; i++ )); do
n="Var${i}Value" # the name of var
[ "${!n+x}" ] || break # see if it exists
echo "$n: '${!n}'"
done
但实际上,您应该使用数组。这里的三个选择都不是标准的,但数组是迄今为止最合乎逻辑的。
VarValue=( A B C )
for value in "${VarValue[@]}"; do
# use "$value" here
printf 'Value is "%s"\n' "$value"
done
也可以看看:
- Bash常见问题解答 006:如何使用可变变量(间接变量、指针、引用)或关联数组?
答案2
这似乎有效:
for ((i=1;i<=3;i++)); do
eval echo "$"$(eval echo Var${i}Value)
done
那里有一个笑话说它很可怕eval
......
答案3
要检查变量是否已设置,请参阅如何检查“if”语句中是否存在变量?( [ -v "Var${i}Value" ]
( ksh
/ zsh
/ bash
) 或eval "[ -n \"\${Var${i}Value+set}\" ]"
(POSIX))。
现在,要循环遍历名称与模式匹配的变量,在 中zsh
,您可以执行以下操作:
for varname in ${(Mk)parameters:#Var<->Value}; do
something with "$varname" and its value: "${(P)varname}"
done
要按数字顺序处理它们,请添加n
参数扩展标志(更改Mk
为Mkn
)。
和bash
:
readarray -t list < <(compgen -v | grep -xE 'Var[[:digit:]]+Value')
for varname in "${list[@]}"; do
something with "$varname" and its value: "${!varname}"
done
或者readarray
用 split+glob 替换 以避免使用数组:
IFS=$'\n' # split on newline
for varname in $(compgen -v | grep -xE 'Var[[:digit:]]+Value'); do
something with "$varname" and its value: "${!varname}"
done
要按数字顺序处理它们并假设您sort
是 GNU sort
,请将输出通过管道传输grep
到sort -V
。
答案4
如果变量已知,则可以使用 For 循环:
例子:
#!/bin/bash
for i in var1 var2 var3
do
echo " This is $i"
#More commands.
done
输出
This is var1
This is var2
This is var3