例如,\c
格式不起作用。我将其输入printf "ABC\ctest"
到 bash 控制台,结果如下;
ABC\ctest
考虑到\c
格式的属性,预期的输出应该是ABC
.
我也没有找到详细说明 bash 上 printf 命令的使用的正确来源。此外,如上面的示例所示,为 printf 命令指定的手册页上的属性无法正常工作。
请给我看一个 bash 的源代码,它详细解释了 printf 命令。因为我现在很困惑。
答案1
printf 'ABC\ctest'
您偶然发现了该命令的未指定部分之一printf
,其行为因实现而异。你把它\c
放在错误的地方了。
如果你读过这单一 Unix 规范的描述printf
仔细地,您会发现\c
没有列在为格式字符串(命令的第一个参数)定义的转义序列列表中。相反,它被定义为额外的给定时可识别的转义序列在参数字符串中就是要格式化的通过%b
格式说明符。
换句话说:
printf '%b\n' 'ABC\ctest'
有明确的行为。这\c
会导致剩余的所有内容(包括格式字符串中的换行符)被忽略。printf '%s\n' 'ABC\ctest'
有明确的行为。\c
首先这不是一个转义序列。printf '\c'
没有明确指定的行为。这不锈钢只是对实际情况保持沉默\c
,没有将其列为转义序列,也没有在其内容中说明文件格式表示法部分这样的序列永远不是转义序列。
不同的 shell 响应这种不符合格式的字符串的行为差异很大。以下是 Debian Almquist、Bourne Again、FreeBSD Almquist、Korn '93 和 Z shell' 反应(其中%
s 显示没有发出换行符的位置):
%破折号-c“printf'ABC\ctest\n'” ABC\c测试 %bash -c "printf 'ABC\ctest\n'" ABC\c测试 %sh -c "printf 'ABC\ctest\n'" ABC% %ksh93 -c "printf 'ABC\ctest\n'" ABCest %zsh -c "printf 'ABC\ctest\n'" ABC% %
我的 MirBSD Korn 和 PD Korn shell 版本没有printf
内置命令。非内置的 FreeBSDprintf
执行以下操作:
%/usr/bin/printf 'ABC\ctest\n' ABC% %
更有趣的是,各种 shell 的 doco 有时具有很强的误导性,甚至有时是完全错误的。举些例子:
- Z shell doco直到最近才开始给出其含义的正确描述
\c
,并将其(通过其 doco forecho
)列为格式字符串中允许的转义序列。 (这是错误的直到2017年, doco 既不同意不锈钢也没有描述 Z shell 实际做了什么。) - Korn '93 shell doco 给出的描述符合不锈钢,但这并不是(如上文所示)它
\c
在格式说明符中实际执行的操作。它也记录\c
为格式字符串的转义序列。它的行为显然是一个错误。 - Bourne Again shell 的 doco和Debian Almquist shell 的 doco
\c
给出匹配的描述不锈钢并明确列出它与%b
(在 Bourne Again shell 的情况下比现在更清楚)截至 2016 年) 和不是printf
在格式说明符的转义序列的一般列表中。这些 shell 不提供此作为标准的扩展。 - FreeBSD Almquist shell doco参照FreeBSD外部
printf
命令手册,其描述\c
符合不锈钢。它明确将其列为格式字符串中允许的转义序列,其实际行为如用户手册中所述。
FreeBSD Almquist shell 和(最近的)Z shell 是唯一的 shell,两个文档都允许\c
在格式字符串中作为转义序列(对标准定义的扩展)和实际上按照记录的方式行事。
讽刺的进一步阅读
答案2
有必要在相应的参数中展开反斜杠转义序列。如中所述这里:
\c Terminate output similarly to the \c escape used by echo -e. printf produces no additional output after coming across a \c escape in a %b argument.
$ printf "%b\n" "ABC\chi"
ABC