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

为什么 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

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

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

系统信息:

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

答案1

格式%*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

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

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

所以:

printf '%*s%c' A B C

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

$ A=5.2*2 zsh -c "printf '%*s%c' A B C"
         BC

BC并在bash// GNU 中输出dash,但也会显示错误消息,因为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

相关内容