首页 > 解决方案 > printf 在执行“printf H%03s 3A”时添加尾随空格而不是 0

问题描述

在我的本地 Mac 上,我开发了一个 bash 脚本,它使用printf. printf这里运行正常:

$ printf H%03s 3A
H03A

字符串3A扩展为 3 个字符,前导零。AnH被添加到变量中。

在我部署 bash 脚本的地方,printf行为不同:

$ printf H%03s 3A
H 3A

我只能假设内部03A被视为八进制值,因此 0 被删除。我怎样才能解决这个问题?

重击版本:

在我的本地 Mac 上,我有 bash 5:

$ echo "$BASH_VERSION"
5.0.3(1)-release

在远程机器上我有 bash 4:

$ echo "$BASH_VERSION"
4.2.46(2)-release

标签: bashprintf

解决方案


printf bash bultin旨在遵循posixprintf。posixprintf实用程序遵循XKB 文件格式表示法,但有一些例外。

好吧,在 XKB 文件格式表示法中,我们可以读到:

标志字符及其含义是:

0
对于 a、A、d、e、E、f、F、g、G、i、o、u、x 和 X 转换说明符,应使用前导零(在任何符号或底数指示之后)填充字段宽度而不是执行空间填充,除非在转换无穷大或 NaN 时。如果'0'和'-'标志都出现,'0'标志将被忽略。对于 d、i、o、u、x 和 X 转换说明符,如果指定了精度,则应忽略“0”标志。对于其他转换说明符,行为未定义。

转换说明符的标志0行为s未定义。

我只能假设内部 03A 被视为八进制值,因此 0 被删除。

不,它不会被解释为八进制数。

我怎样才能解决这个问题?

我想出的最简单的是用零替换空格:

printf 'H%5s' "$(printf "%5s" 3A | tr ' ' '0')"

这很简单,但如果字符串中有空格,肯​​定会失败。所以我们需要测量字符串长度并在字符串前面输出那么多零,例如。像这样的东西:

printf 'H%5s' "$(str=3A; seq $((5 - ${#str})) | xargs printf '0%.0s'; printf "%s" "$str")"

推荐阅读