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
今天我被告知那个壳内置 printf
s 没有这个限制;测试:
printf '%s\n' $(seq $(( $(getconf ARG_MAX) * 2 ))) | tail -1
输出:
4194304
问题:
略读
man bash dash
似乎并没有太多说明这个优点内置printf
。在哪里是它有记录吗?做内置
printf
s(例如bash
)有一个以字符为单位的参数列表最大长度,如果是,那么该长度是多少?
答案1
提倡使用任何特定实用程序并不是手册的真正职责。主要应该是描述可用的内置实用程序。
与外部实用程序相比,使用内置实用程序的优点主要在于速度和扩展功能的可用性(printf
例如bash
,可以直接写入变量-v varname
,而外部程序printf
永远无法做到这一点)。
与执行内置实用程序相比,执行外部实用程序很慢,特别是如果经常在循环中执行,并且正如您所注意到的,它们还允许更长的参数列表(这不是只有内置程序才printf
允许的) ,但所有内置实用程序)。
内置printf
实用程序的参数列表的长度受到进程本身bash
资源限制的限制bash
。在某些系统上,这甚至可能意味着您可以使用大部分可用 RAM 来构建其命令行参数列表。
您可以在其中找到这些各种信息的文档是
一个 shell 的例子,printf
其中不是内置实用程序是ksh
OpenBSD 的外壳。该实用程序还可以残疾人在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 的文件;-)