【问题标题】:strange behavior when fixing integer lengths in bash在 bash 中修复整数长度时的奇怪行为
【发布时间】:2018-02-27 01:23:16
【问题描述】:

在我的 bash 脚本中,我设置了以下操作

year=0050
echo $(printf %04d $year)
>0040

我不明白为什么返回 0040 而不是 0050。我最终发现要让系统正确打印 0050,我将不得不这样做。

year=50
echo $(printf %04d $year)
>0050

对于第一个案例发生的原因有什么见解吗?

【问题讨论】:

  • 如果你的号码以0开头,它被解释为八进制;八进制 50 是十进制 40。
  • 0 开头的printf 的数字参数被解释为八进制数。另外,你为什么打电话给echo $(printf ...)echoprintf 都打印它们的输出。您可以删除echo
  • @larsks 也许是因为换行,但显然,使用%04d\n 解决这个问题更好。
  • @larsks 我打电话给 echo 因为我还将月份和日期组合成一个 8 位数的日期,所以整行看起来像: echo $(printf %04d $year)$(printf %02d $month)$(printf %02d $day)
  • 您应该使用单个 printf 语句来代替,例如 printf '%04d%02d%02d\n' "$year" "$month" "$day"

标签: bash integer printf decimal octal


【解决方案1】:

这是因为带有前导零的数字被 Bash 解释为八进制,而八进制 50 是十进制 40。

要修复它,您可以使用参数扩展去除零:

$ printf '%04d\n' "${year##+(0)}"
0050

我已经删除了echo $(...) 结构,而是在格式化字符串中插入了一个换行符。

请注意,+(0) 模式需要 extglob shell 选项 (shopt -s extglob)。

或者(并且更便携),您可以先使用算术扩展来转换数字:

% printf '%04d\n' "$(( 10#$year ))"
0050

这使用<i>base</i>#<i>n</i> 表示法来表示n(在我们的例子中:$year)是以 10 为底,而不是八进制。

【讨论】:

    猜你喜欢
    • 2018-02-12
    • 1970-01-01
    • 2020-12-03
    • 1970-01-01
    • 2019-03-19
    • 1970-01-01
    • 2017-10-23
    • 1970-01-01
    • 2011-07-05
    相关资源
    最近更新 更多