3

在学习 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 的值。但显然它没有为什么?

4

2 回答 2

3

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

因为*在 shell 中具有特殊含义,它是一个全局扩展,列出了当前文件夹中的所有文件/目录。您还可以看到一个条目说明其他两个字符串按字面意思解释。

来自man bash(1)页面下的部分Expansion

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

如果您的目标是用于 bourne again shell 的脚本,则最好使用for带有构造的循环((..))

for ((i=1; i<=38; i++)); do
于 2018-01-06T09:09:55.853 回答
2

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

于 2018-01-06T09:08:13.983 回答