Shell 内置 `printf` 行数限制?

Shell 内置 `printf` 行数限制?

util 参数列表/usr/bin/printf长度限制为 shell 的最大命令行长度(IE getconf ARG_MAX,在我的系统上是2097152);例子:

# try using a list that's way too long
/usr/bin/printf '%s\n' $(seq $(( $(getconf ARG_MAX) * 2 ))) | tail -1

输出:

bash: /usr/bin/printf: Argument list too long

今天我被告知那个壳内置 printfs 没有这个限制;测试:

printf '%s\n' $(seq $(( $(getconf ARG_MAX) * 2 ))) | tail -1

输出:

4194304

问题:

  1. 略读man bash dash似乎并没有太多说明这个优点内置 printf。在哪里它有记录吗?

  2. 内置 printfs(例如 bash)有一个以字符为单位的参数列表最大长度,如果是,那么该长度是多少?

答案1

提倡使用任何特定实用程序并不是手册的真正职责。主要应该是描述可用的内置实用程序。

与外部实用程序相比,使用内置实用程序的优点主要在于速度和扩展功能的可用性(printf例如bash,可以直接写入变量-v varname,而外部程序printf永远无法做到这一点)。

与执行内置实用程序相比,执行外部实用程序很慢,特别是如果经常在循环中执行,并且正如您所注意到的,它们还允许更长的参数列表(这不是只有内置程序才printf允许的) ,但所有内置实用程序)。

内置printf实用程序的参数列表的长度受到进程本身bash资源限制的限制bash。在某些系统上,这甚至可能意味着您可以使用大部分可用 RAM 来构建其命令行参数列表。

您可以在其中找到这些各种信息的文档是

  • bash代码,您将在其中看到参数列表printf是一个动态分配的链表,而且它是不是使用execve()运行printf(这是运行外部实用程序时限制参数列表长度的原因)。

一个 shell 的例子,printf其中不是内置实用程序是kshOpenBSD 的外壳。该实用程序还可以残疾人bash使用enable -n printf

答案2

/usr/bin/printf util 参数列表长度限制为 shell 的最大命令行长度(即 getconf ARG_MAX,在我的系统上为 2097152);例子:

那不是一个的限制,而是操作系统(Linux 内核)的限制,特别是其execve(2)系统调用的限制,并且是由命令行参数和环境变量传递到启动程序的过时方式引起的。

(请注意,该限制还包括环境变量!)。

略读 man bash dash 似乎并没有过多说明内置 printf 的这一优势。它记录在哪里?内置 printfs 是否有参数列表长度(例如 bash),如果有,它是什么?

由于 shell 内置函数不会通过,execve(2)因此不必有任何这样的限制。现代 shell 通常不使用固定大小的缓冲区等,因此限制通常是由可用内存量和虚拟地址空间的布局所施加的——即,它对于所有意图和目的都是无限的。

答案3

POSIX 标准要求 shell 的实现没有行数限制。

所以这是 shell 没有记录的自然现象。

顺便说一句:因此,shell 脚本可能不是文本文件,因为文本文件是行数不超过 LINE_MAX 的文件;-)

相关内容