来自bash one liner的奇怪输出

时间:2018-01-06 09:04:45

标签: linux bash glob brace-expansion

在学习bash的过程中,我经常调整现有的东西,看看它的输出。

~$ for i in {1..19}; do echo "Everything in UNIX is a file."; sleep 1; done

我有这个,出于好奇,我将上面的内容调整为以下内容: -

~$ for i in {1..19 * 2}; do echo "Everything in UNIX is a file."; echo "The value of i is ${i}";  sleep 1; done

令我惊讶的是,我开始得到以下输出: -

Everything in UNIX is a file.
The value of i is OneDrive
Everything in UNIX is a file.
The value of i is opera autoupdate
Everything in UNIX is a file.
The value of i is Personal_Workspace
Everything in UNIX is a file.
The value of i is Pictures
Everything in UNIX is a file.
The value of i is PrintHood
Everything in UNIX is a file.
The value of i is Recent
Everything in UNIX is a file.
The value of i is Roaming
Everything in UNIX is a file.
The value of i is Saved Games
Everything in UNIX is a file.
The value of i is Searches

i的一些值是我的主目录中的文件和目录的名称,我在主目录中,同时执行此脚本。

我期待i值的范围从1到19 * 2 = 38,所以我会从1,2,3 ...... 30 ...... 38取值。 但显然它没有为什么?

2 个答案:

答案 0 :(得分:3)

bash中,是的,范围扩展发生在其他所有事情之前。您期望算术扩展发生由于扩展bash shell的顺序,未按预期发生。您的代码最终将{1..19*2}解释为文字字符串。

由于*在shell中具有特殊含义,因此它是一个包含当前文件夹中所有文件/目录的glob扩展。你也可以看到一个条目,说明字面上解释的其他两个字符串。

来自Expansion

部分下的man bash(1)页面
  

扩展的顺序是:大括号扩展,波浪扩展,参数,变量和算术扩展以及命令替换(以从左到右的方式完成),单词拆分和路径名扩展。

如果你再次为bourne定位脚本shell,那么你最好使用带有for构造的((..))循环

for ((i=1; i<=38; i++)); do

答案 1 :(得分:2)

unix shell中的*符号转换为通配符,因此{1..19 * 2}的含义基本上是1到19,当前目录中的所有文件(即*),而不是2这些将是你循环中i的值