`for i in {1..$N}` 和 `for i in $(seq 1 1 $N) ` 之间的区别

Mar*_*tus 6 bash

我在脚本中有以下内容:

#!/usr/bin/env bash 
...
for i in {1..$N}
   <loop content>
Run Code Online (Sandbox Code Playgroud)

以上不起作用,仅在i具有值的地方执行一次{1..5} (如果5作为参数提供)。

如果我将上述内容替换为:

for i in $(seq 1 1 $N)
Run Code Online (Sandbox Code Playgroud)

..然后事情按预期工作。这是为什么?

Sté*_*las 10

{1..8}是括号扩展的形式通过引入zsh并通过最新版本的支持bashksh93。在bash,它很早就完成了。特别是,它是在之前完成的变量扩展。

虽然{1..8}有效,但{1..$N}不是因为$N不是十进制数,而是两个字符$N没有一个是十进制数字。

即使这样有效,那也不会很有效率。shell 必须在内存中分配一个由数字 1 到$N. 如果$N是 10 9,那将意味着分配千兆字节的内存。

$(seq "$N")效率更低。首先,它不便携。seq是一个非标准的 GNU 命令。然后执行$(seq "$N")意味着启动一个新进程,seq在其中执行,shell 通过管道读取其输出并将其存储在内存中,然后拆分该列表(根据$IFS)并尝试对其执行文件名生成。

还必须为由拆分和通配生成的列表分配空间。

一种更有效的方法是使用ksh for (( ))循环样式(也得到了支持bashzsh持续了几十年)。

for ((i = 1; i <= N; i++)); do
   <loop content>
done
Run Code Online (Sandbox Code Playgroud)

或者简单地以可移植和标准的方式编写它,因此您甚至不必使用bash,并且可以使用您的(可能更快/更精简)系统的sh

i=1
while [ "$i" -le "$N" ]; do
  <loop content>
  i=$(($i + 1))
done
Run Code Online (Sandbox Code Playgroud)

或者,也许您可​​以通过完全避免循环来以 shell 方式执行更多操作。但我们需要知道你最终想做什么来帮助那里。