我正在尝试在shell脚本中生成动态var名称,以在循环中处理一组具有不同名称的文件,如下所示:
#!/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
Run Code Online (Sandbox Code Playgroud)
我期待输出:
1-first.with.custom.name
2-second.with.custom.name
Run Code Online (Sandbox Code Playgroud)
但我得到了:
SAMPLE{1}
SAMPLE{2}
Run Code Online (Sandbox Code Playgroud)
是否有可能在飞行中生成var名称?
joh*_*n64 69
您需要使用变量间接:
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
Run Code Online (Sandbox Code Playgroud)
在Bash手册页的 "参数扩展"下:
"如果参数的第一个字符是感叹号(!),则引入一个变量间接的级别.Bash使用从参数的其余部分形成的变量的值作为变量的名称;然后扩展该变量并且value用于替换的其余部分,而不是参数本身的值.这称为间接扩展."
Tod*_*obs 18
您正在使用i的值,就好像它是一个数组索引一样.它不是,因为SAMPLE1和SAMPLE2是单独的变量,而不是数组.
此外,在呼叫时,echo SAMPLE{$i}您只将i的值附加到单词"SAMPLE".您在此声明中解除引用的唯一变量是$ i,这就是您获得结果的原因.
有两种主要方法可以解决这个问题:
在这种情况下最简单的方法是使用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
Run Code Online (Sandbox Code Playgroud)
这会将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
Run Code Online (Sandbox Code Playgroud)
这在技术上是一个三步过程.首先,它为var分配一个插值变量名,然后取消引用存储在var中的变量名,最后展开结果.它看起来有点干净,有些人对这种语法比使用eval更舒服,但结果基本相同.
您可以通过迭代数组而不是使用变量插值来简化循环和扩展.例如:
SAMPLE=('1-first.with.custom.name' '2-second.with.custom.name')
for i in "${SAMPLE[@]}"; do
echo "$i"
done
Run Code Online (Sandbox Code Playgroud)
与其他方法相比,这增加了优势.特别:
所有这三种方法都适用于原始问题中给出的示例,但阵列解决方案提供了最大的整体灵活性.选择最适合您手头数据的那个.