【问题标题】:Convert string into integer in bash script - "Leading Zero" number error在 bash 脚本中将字符串转换为整数 - “前导零”数字错误
【发布时间】:2019-09-20 01:07:48
【问题描述】:

在文本文件 test.txt 中,我有以下信息:

sl-gs5 desconnected Wed Oct 10 08:00:01 EDT 2012 1001

我想通过下一个命令行提取事件的时间:

hour=$(grep -n sl-gs5 test.txt | tail -1 | cut -d' ' -f6 | awk -F ":" '{print $1}')

我得到了“08”。当我尝试加 1 时,

 14 echo $((hour+1))

我收到下一条错误消息:

./test2.sh: line 14: 08: value too great for base (error token is "08")

如果 Bash 中的变量没有类型,为什么?

【问题讨论】:

  • 前导 0 导致 bash 试图将您的数字解释为八进制数,但八进制数是 0-7,因此 8 是无效标记。
  • 此错误来自“前导零”错误,也就是 bash 中第一个非零表示之前出现的任何 0 数字。示例(例如 01,002、0000003 等...)

标签: bash


【解决方案1】:

参见man bash中的算术评估

以 0 开头的常量被解释为八进制数。

您可以通过参数扩展来去除前导零

hour=${hour#0}

或强制 base-10 解释:

$((10#$hour + 1))

【讨论】:

  • 您也可以强制使用 base-10 解释:$((10#$hour+1))
  • 这不适用于我的 bash 和负数:lat=-048 ; latd=${lat#0} ; echo $latd ; echo $((latd-1)) 给了我-048,然后是同样的错误。
  • @LuisA.Florit:当然,#0 会从字符串的开头删除零,取而代之的是-。使用shopt -s extglob ; latd=${latd#?(-)0}
  • 问题在于你得到的是绝对值(在示例中,47 而不是-49。似乎这需要更长的单行线,可能是sedbc 或我想避免的事情,因为我的在一个大循环中。我讨厌这个八进制的东西bash 做。应该可以用shopt 配置它。
  • 带有可选前导+-的数字可以用$((${hour%%[^-+]*}10#${hour#[-+]}))处理
【解决方案2】:

我称之为 hack,但鉴于您只处理小时值,您可以这样做

 hour=08
 echo $(( ${hour#0} +1 ))
 9
 hour=10 
 echo $(( ${hour#0} +1))
 11

风险很小。

IHTH。

【讨论】:

    【解决方案3】:

    你也可以使用bc

    hour=8
    result=$(echo "$hour + 1" | bc)
    echo $result
    9
    

    【讨论】:

    • 它对我有用,所以 +1 但是,我正在寻找一些简单的解决方案,例如 result=int("$hour + 1")
    【解决方案4】:

    这是一种简单的方法,虽然不是获取字符串 int 值的最漂亮的方法。

    hour=`expr $hour + 0`
    

    例子

    bash-3.2$ hour="08"
    bash-3.2$ hour=`expr $hour + 0`
    bash-3.2$ echo $hour
    8
    

    【讨论】:

    • 这只会产生字符串08+0
    • 你在用什么外壳@JimGarrison
    • 为我工作。谢谢!
    【解决方案5】:

    简而言之:为了在 bash 中处理“前导零”数字(第一个非零之前的任何 0 数字) - 使用bc 任意精度的计算器语言

    例子:

    a="000001"
    b=$(echo $a | bc)
    echo $b
    

    输出:1

    来自 Bash 手册:

    "bc 是一种支持任意精度数字并具有交互执行能力的语言 的陈述。语法与 C 编程语言有一些相似之处- 计。标准数学库可通过命令行选项获得。如果要求, 在处理任何文件之前定义数学库。 bc 首先处理来自的代码 命令行上按列出的顺序列出的所有文件。在所有文件都有 被处理后, bc 从标准输入中读取。所有代码都在读取时执行。 (如果文件包含停止处理器的命令,bc 将永远不会从标准输入中读取。)"

    【讨论】:

      【解决方案6】:

      由于小时数始终为正数,且始终为 2 位数,因此您可以在其前面设置一个 1 并减去 100:

      echo $((1$hour+1-100))
      

      相当于

      echo $((1$hour-99))
      

      请务必评论此类体操。 :)

      【讨论】:

        【解决方案7】:

        sed 怎么样?

        hour=`echo $hour|sed -e "s/^0*//g"`
        

        【讨论】:

          【解决方案8】:

          前导 0 导致 bash 试图将您的数字解释为八进制数,但八进制数是 0-7,因此 8 是无效标记。

          如果我是你,我会添加一些逻辑来删除前导 0,添加 1,如果结果为

          【讨论】:

            猜你喜欢
            • 2019-07-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多