为什么在 bash 的 printf 内置函数中只有一些字母被认为是无效数字?

Gra*_*ent 0 bash printf

我在胡闹,忘了删除printf语句的一部分,得到了这个输出:

# printf '%*s%c' {A..Z}
bash: printf: A: invalid number
bash: printf: D: invalid number
bash: printf: G: invalid number
bash: printf: J: invalid number
bash: printf: M: invalid number
bash: printf: P: invalid number
bash: printf: S: invalid number
bash: printf: V: invalid number
bash: printf: Y: invalid number
BCEFHIKLNOQRTUWXZ
Run Code Online (Sandbox Code Playgroud)

为什么被BCEFHIKLNOQRTUWXZ认为是有效数字?我认为这是因为它们可能是格式字符,但这似乎并不能解释Z.

有什么地方可以阅读/了解更多相关信息吗?

系统信息:

  • GNU bash,版本 4.4.12(1)-release (x86_64-unknown-linux-gnu)

Sté*_*las 5

%*s格式规范消耗两个参数像在C,一个用于填充的宽度和一个用于字符串填充。

printf如果在前几轮消耗完参数后仍有剩余参数,则该实用程序会继续重用该格式:

例如,这将用作:

$ printf '%*s%c' 3 x1 '|' 4 y1  '|' 3 z1 "$NL" \
                 3 x2 '|' 4 y22 '|' 3 z2 "$NL"
 x1|  y1| z1
 x2| y22| z2
Run Code Online (Sandbox Code Playgroud)

按列格式化输出。现在,对于这些宽度参数的预期,行为取决于printf实现。

  • 对于内置的zsh和 AT&T ksh,它可以是任何算术表达式(就像在大多数需要数字的地方一样)。所以,1+1或 2 表示相同。A作为算术表达式解析为 的值$A,或者 0 是$A未设置或为空。
  • GNUprintfprintf内置的bashanddash仅接受十进制、八进制或十六进制文字常量(因此 020、16 和 0x10 表示相同),忽略前导(但不是尾随)空格并返回错误消息(但如果在以下位置找到,则使用任何有效数字)参数的开头或 0 如果没有)如果它不被识别为有效数字。
  • yashprintf内置当前不支持%*s

所以:

printf '%*s%c' A B C
Run Code Online (Sandbox Code Playgroud)

将输出BCin kshandzsh除非$A包含一个算术表达式,该表达式解析为一个整数部分不是 0 的数字。

$ A=5.2*2 zsh -c "printf '%*s%c' A B C"
         BC
Run Code Online (Sandbox Code Playgroud)

BCbash/ dash/GNU 中输出,但还有一条错误消息,因为A它不是有效的十进制/八进制/十六进制文字常量。

zsh或者ksh如果算术表达式无效,则可能会输出错误消息,并且与计算算术表达式的任何地方一样,也可能使用环境中的错误变量运行任意命令:

$ A=1+ zsh -c "printf '%*s%c' A B C"
zsh:1: bad math expression: operand expected at end of string
BC
$ A='psvar[0$(uname>&2)]' zsh -c "printf '%*s%c' A B C"
Linux
BC
Run Code Online (Sandbox Code Playgroud)