如何在 shell 脚本中动态生成新的变量名?
- 2024-10-11 08:36:00
- admin 原创
- 71
问题描述:
我正在尝试在 shell 脚本中生成动态变量名称,以便循环处理一组具有不同名称的文件,如下所示:
#!/bin/bash
SAMPLE1='1-first.with.custom.name'
SAMPLE2='2-second.with.custom.name'
for (( i = 1; i <= 2; i++ ))
do
echo SAMPLE{$i}
done
我期望输出:
1-first.with.custom.name
2-second.with.custom.name
但我得到:
SAMPLE{1}
SAMPLE{2}
是否有可能动态生成变量名称?
解决方案 1:
您需要利用变量间接寻址:
SAMPLE1='1-first.with.custom.name'
SAMPLE2='2-second.with.custom.name'
for (( i = 1; i <= 2; i++ ))
do
var="SAMPLE$i"
echo ${!var}
done
在Bash 手册页的‘参数扩展’下:
“如果参数的第一个字符是感叹号 (!),则引入了变量间接层。Bash 使用由参数其余部分形成的变量的值作为变量的名称;然后扩展此变量,并在其余替换中使用该值,而不是参数本身的值。这称为间接扩展。”
解决方案 2:
问题
您将i的值当作数组索引来使用。但事实并非如此,因为 SAMPLE1 和 SAMPLE2 是独立的变量,而不是数组。
此外,调用时,您仅将iecho SAMPLE{$i}
的值附加到单词“SAMPLE”。您在此语句中取消引用的唯一变量是$i,这就是您获得结果的原因。
解决问题的方法
有两种主要方法可以解决此问题:
通过eval内置函数或间接变量扩展,对插值变量进行多阶段取消引用。
遍历数组,或使用i作为数组的索引。
使用eval取消引用
在这种情况下最简单的方法是使用eval:
SAMPLE1='1-first.with.custom.name'
SAMPLE2='2-second.with.custom.name'
for (( i = 1; i <= 2; i++ )); do
eval echo $SAMPLE${i}
done
这会将i的值附加到变量的末尾,然后重新处理结果行,扩展插值的变量名称(例如SAMPLE1或SAMPLE2)。
使用间接变量取消引用
该问题可接受的答案是:
SAMPLE1='1-first.with.custom.name'
SAMPLE2='2-second.with.custom.name'
for (( i = 1; i <= 2; i++ ))
do
var="SAMPLE$i"
echo ${!var}
done
从技术上讲,这是一个三步过程。首先,它将一个插值变量名分配给var ,然后取消引用存储在var中的变量名,最后扩展结果。它看起来更简洁一些,有些人更喜欢这种语法而不是eval,但结果大致相同。
迭代数组
您可以通过迭代数组而不是使用变量插值来简化循环和扩展。例如:
SAMPLE=('1-first.with.custom.name' '2-second.with.custom.name')
for i in "${SAMPLE[@]}"; do
echo "$i"
done
与其他方法相比,这种方法具有更多优势。具体来说:
您不需要指定复杂的循环测试。
您可以通过$SAMPLE[$i]语法访问单个数组元素。
您可以使用${#SAMPLE}变量扩展获取元素的总数。
原始示例的实际等效性
对于原始问题中给出的示例,所有三种方法都适用,但数组解决方案提供了最全面的灵活性。选择最适合您手头数据的方法。
解决方案 3:
eval
您可以按照如下所示使用:
SAMPLE1='1-first.with.custom.name'
SAMPLE2='2-second.with.custom.name'
for (( i = 1; i <= 2; i++ ))
do
eval echo $SAMPLE$i
done
解决方案 4:
据我所知不是, @johnshen64 是这样说的。此外,您可以使用如下数组解决问题:
SAMPLE[1]='1-first.with.custom.name'
SAMPLE[2]='2-second.with.custom.name'
for (( i = 1; i <= 2; i++ )) do
echo ${SAMPLE[$i]}
done
请注意,您不需要使用数字,因为索引SAMPLE[hello]
也可以正常工作
解决方案 5:
这不是一个独立的答案,只是对 Miquel 答案的补充,我无法在评论中很好地表达出来。
您可以使用循环、+= 运算符以及此处的文档来填充数组:
SAMPLE=()
while read; do SAMPLE+=("$REPLY"); done <<EOF
1-first.with.custom.name
2-second.with.custom.name
EOF
在 bash 4.0 中,非常简单
readarray SAMPLE <<EOF
1-first.with.custom.name
2-second.with.custom.name
EOF
解决方案 6:
eval “回显 $SAMPLE${i}”
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件