man printf
,info printf
而且printf --help
对我来说都毫无用处;我想要对选项的解释FORMAT
。例如,我可以使用:
printf '%s\n' foo bar
并得到输出:
foo
bar
从网上的一般阅读来看,我推测这%s
意味着类似“分隔符”的东西,因此它printf
会打印提供给它的每个参数,并用换行符分隔。
我还在这里和那里看到了参考文献%d
以及其他一些参考文献(我认为这与数字有关?)。有人可以概述一下这些格式选项吗?
答案1
对于 bash,主要资源是man bash
.特别是对于内置函数,有help
内置函数。这是来自 的引用help printf
。
除了 printf(1) 和 printf(3) 中描述的标准格式规范外,printf 还解释:
%b expand backslash escape sequences in the corresponding argument %q quote the argument in a way that can be reused as shell input %(fmt)T output the date-time string resulting from using FMT as a format string for strftime(3)
printf(N)
中使用的符号意味着help printf
您应该参考括号中数字表示的命令的手册部分。
如果您需要特殊的 %(fmt)T 说明符,请参见man 1 printf
、 、 和 。man 3 printf
man 3 strftime
你必须自己把它们拼凑起来;该文档并没有简单地列出“%s 表示字符串,%d 表示数字”。我相信您要求的首要任务是转换规范。
答案2
我发现的最好的资源是bash-hackers.org 维基对于所有与 Bash 相关的事情。这才是手册页应该有的样子,而不是一堆难以浏览的内容。
内置有特定主题,包括printf
。这一页很详尽!它包括所有格式选项以及示例,甚至底部的讨论部分,以帮助充实我们的极端情况和printf
功能的细微差别。
我也知道使用有关 printf 的 GNU Coreutils 文档,特别是页面格式选项,在紧要关头。
答案3
首先,区分以下三个printf
品种很重要:
printf
作为一场狂欢内置。printf
作为(Bash-)外部可执行文件,例如核心工具的/usr/bin/printf
(参见which printf
和man 1 printf
)。printf(..)
来自C标准库(库)(就我而言,它是GNU 项目 glibc实施,参见man 3 printf
第一步是确定执行时使用的是内置可执行版本还是外部可执行版本命令 printf '%s\n' foo bar
。这可以使用以下方法找到type
Bash 内置在使用的特定 shell 提示符上:
$ type printf
printf is a shell builtin
这Bash 内置 printf
记录在Bash 参考手册 - 4.2 Bash 内置命令:printf
。
虽然 Bash 文档没有对%s
或进行任何解释%d
,但它包含以下相关信息:
除了标准
printf(1)
格式之外,printf 还解释以下扩展:[...]
在我的系统上(Debian 11 靶心)man 1 printf
表明printf
可执行文件来自GNU 核心工具。
要使用该可执行文件(而不是内置命令)运行命令,请使用以下任一语句:
env printf '%s\n' foo bar
/usr/bin/printf '%s\n' foo bar
# full path to the printf *executable* found out via command 'which printf'
这coreutils可执行文件 printf
记录在GNU Coreutils - 15.2 printf
:格式化和打印数据。
coreutils 文档包含以下相关信息:
printf
打印格式字符串,解释 '%
' 指令和 '\
' 转义符以格式化数字和字符串参数,其方式与 C 'printf
' 函数非常相似。看printf
格式指令有关详细信息,请参阅 GNU C 库参考手册。下面列出了差异。 [...]
coreutils 文档已经提供了有关%s
和 的附加说明%d
。
所引用的GNU C 库参考手册有以下相关部分printf(..)
:
- GNU C 库参考手册 - 12.12 格式化输出
- GNU C 库参考手册 - 12.12.1 格式化输出基础知识
- GNU C 库参考手册 - 12.12.3 输出转换表
'
%d
'、'%i
':将整数打印为带符号的十进制数。看整数转换,了解详情。 [...]
'%s
':打印字符串。看其他输出转换。 [...] - GNU C 库参考手册 - 12.12.4 整数转换
'
%d
' 和 '%i
' 转换规范都将 int 参数打印为带符号的十进制数; [...] - GNU C 库参考手册 - 12.12.6 其他输出转换
'
%s
' 转换打印一个字符串。如果不存在 'l
' 修饰符,则相应的参数必须是类型char * (or const char *)
。 [...] - GNU C 库参考手册 - 12.12.7 格式化输出函数
功能:int printf (const char *template, ...) [...]
最后:GNU C 库是(也)是一个执行的C POSIX 库 标准,或多或少符合其中给出的规范。
POSIX正式名称(最新版本)为POSIX.1-2017, 和IEEE 标准 1003.1-2017, 和Open Group 技术标准基本规范,第 7 期。该规范提供了关于如何printf(..)
“根据规范”工作的“官方”规则。
- POSIX.1-2017 规范首页
- POSIX.1-2017 - “系统接口”卷
- POSIX.1-2017 - dprintf、fprintf、printf、snprintf、sprintf - 打印格式化输出
[...] 此参考页中描述的功能符合 ISO C 标准。此处描述的要求与 ISO C 标准之间的任何冲突都是无意的。本卷 POSIX.1-2017 遵循 ISO C 标准。 [...]
[...] printf() 函数应将输出放在标准输出流 stdout 上。
[...] 这些函数中的每一个都在格式的控制下转换、格式化和打印其参数。格式是一个字符串,以其初始移位状态(如果有)开始和结束。该格式由零个或多个指令组成:普通字符(仅复制到输出流)和转换规范(每个指令都将导致获取零个或多个参数)。如果格式参数不足,则结果不确定。如果格式已用尽而参数仍然存在,则应评估多余的参数,但否则将被忽略。 [...]
[...] 在包含 % 形式的转换规范的格式字符串中,每个转换规范使用参数列表中第一个未使用的参数。 [...]
[...] 每个转换规范均由 ' 引入%' 字符 [...],其后按顺序出现以下内容: [...] 转换说明符字符,指示要应用的转换类型。 [...]
转换说明符及其含义是:
d,i:int 参数应转换为“[-]dddd”样式的有符号十进制。精度指定出现的最小位数;如果要转换的值可以用更少的位数表示,则应使用前导零进行扩展。默认精度为 1。使用显式精度为零转换零的结果不应为任何字符。
[...]
s:参数应是指向字符数组的指针。数组中的字节应写入(但不包括)任何终止空字节。如果指定了精度,则写入的字节数不得超过该数量。如果未指定精度或精度大于数组的大小,则应用程序应确保数组包含空字节。
[...]
- POSIX.1-2017 - dprintf、fprintf、printf、snprintf、sprintf - 打印格式化输出
- POSIX.1-2017 - “系统接口”卷
显然,要完全深入了解定义,下一步将是查看适当的“ISO C 标准”(也称为“ANSI C”)修订版,正式指定于ISO/IEC 9899,例如在修订中ISO/IEC 9899:2018,也称为C17。查找 ISO C 标准修订版的官方完整规范并不那么容易,正如这个 StackOverflow 问题所示。
但可以说,要找出“Bash 的内置printf
格式选项”对于更奇特的变种的预期含义和实际行为,可能需要深入研究几层实现、抽象和规范。
同样重要
请记住,这些软件的不同版本可能具有不同的可用选项,并且可能会更改现有选项的语义。最佳做法是参考与正在使用的版本匹配的手动版本。例如 GNU C 库参考手册提供版本控制的手动版本。