bash 一个班轮的奇怪输出

Strange output from bash one liner

在学习过程中 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的部分值是我的home目录下的文件名和目录名,我在home目录下执行这个脚本

我期望 i 值的范围是 1 到 19*2 = 38,所以我会取 1,2,3...30...38 之间的值。 但是明明没有为什么?

Unix 中的 * 符号 shell 转换为通配符,所以基本上 {1..19 * 2} 的意思是 1 到 19,当前目录中的所有文件(即 *),以及比 2. 这些将是 i 在你的循环中的值

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

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

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

The order of expansions is: brace expansion, tilde expansion, parameter, variable and arithmetic expansion and command substitution (done in a left-to-right fashion), word splitting, and pathname expansion.

如果您再次针对伯恩 shell

,最好使用带有 ((..)) 构造的 for 循环
for ((i=1; i<=38; i++)); do