在同一语句中多次使用bash for循环变量

时间:2014-06-10 08:15:12

标签: bash

我遇到了一个我觉得很奇怪的问题,我希望有人可以解释一下。我设置了一个简单的bash for循环,它迭代一些数字并复制文件名中每个数字两次的文件。如果不使用${var_name},则会失败,但在执行此操作时会成功。这是一个简短的例子,解释了我的意思:

$ touch 123.foo.123bar
$ touch 456.foo.456bar
$ mkdir out
$ for i in {123,456}; do cp $i.foo.$ibar out; done
cp: cannot stat `123.foo.': No such file or directory
cp: cannot stat `456.foo.': No such file or directory
$ for i in {123,456}; do cp ${i}.foo.${i}bar out; done
$ ls out
123.foo.123bar  456.foo.456bar

第一个失败的原因是什么?第二个失败的原因是什么?

3 个答案:

答案 0 :(得分:3)

如果你写$ibar,bash会将其理解为${ibar}。确实,它应该在哪里结束变量名称? (变量名中不允许使用点,因此$i.不会导致问题。)

另一种防止问题的方法是使用反斜杠:

cp $i.foo.$i\bar out

答案 1 :(得分:1)

您的第一个示例引用了未定义的变量$ibar。 第二个明确使用$i,这是你想要的。

变量名称由bash扩展,直到第一个单词分隔符,因此$i.foo将被解析为${i}.foo,因为.会终止该单词。

但是,$ibar只会在空白处结束,因此bash会在范围内查找${ibar}

答案 2 :(得分:1)

在正常命令中使用双引号("")引用带有变量的参数始终是一个好习惯,以防止意外的单词拆分和路径名扩展:

cp "$i.foo.$ibar" out

如果您发现变量与有效变量字符相邻,则首选解决方案始终是使用${}格式将其隔离。引用(如cp "$i.foo.$i\bar" out)可能会因实施而产生混淆:

cp "${i}.foo.${i}bar" out

大部分时间使用${}也不错。