当运行我的bash脚本的这一部分时,我得到了一个错误
编写脚本
value=0
for (( t=0; t <= 4; t++ ))
do
d1=${filedates[$t]}
d2=${filedates[$t+1]}
((diff_sec=d2-d1))
SEC=$diff_sec
compare=$((${SEC}/(60*60*24)))
value=$((value+compare))
done
输出
jad.sh: line 28: ((: 10#2014-01-09: value too great for base (error token is "09")
jad.sh: line 30: /(60*60*24): syntax error: operand expected (error token is "/(60*60*24)")
d1和d2是2014-01-09和2014-01-10 格式的日期
有什么解决方案吗?
在变量前面加上字符串"10#"。这迫使bash将它们视为十进制,即使前导零通常会使它们成为八进制。
什么是d1
和d2
?它们是日期还是秒?
通常,如果您试图对包含零前缀的数字(例如09)进行算术运算,就会出现此错误。
示例:
$ echo $((09+1))
-bash: 09: value too great for base (error token is "09")
为了使用前缀为0的数字执行算术运算,您需要通过指定10#
:来告诉bash使用基数为10的数字
$ echo $((10#09+1))
10
正如其他人所说,错误是由Bash将以零开头的数字序列解释为八进制数引起的。如果您可以控制创建日期值的过程,并且您使用的是date
,则可以在输出格式字符串前面加一个连字符,以删除前导零填充。
不在date
格式前加连字符:
$ (( $(date --date='9:00' +%H) < 10 )) && echo true || echo oops
-bash: ((: 09: value too great for base (error token is "09")
oops
在date
格式前加上连字符:
$ (( $(date --date='9:00' +%-H) < 10 )) && echo true || echo oops
true
来自date
手册页:
默认情况下,日期用零填充数字字段。以下内容可选标志可能跟在"%"后面:
- (hyphen) do not pad the field
d1和d2是2014-01-09和2014-01-10 格式的日期
然后
((diff_sec=d2-d1))
你期望得到什么?((diffsec=2014-01-09-2014-01-10))
??
您需要先将日期转换为秒:
d1=$( date -d "${filedates[$t]}" +%s )
d2=$( date -d "${filedates[$t+1]}" +%s )
(( compare = (d2 - d1) / (60*60*24) ))
(( value += compare ))
在此处发布一些与本问题标题相关的提示,但与原始问题的详细信息没有直接关系。我意识到这在Stack Overflow上有点争议,但这些相关问题:
在bash〔duplicate〕中将八进制转换为十进制
值对于基本值太大(错误标记为"08")[重复]
指向这个,,但它们是关闭的,因此,我无法在那里发布这个答案。因此,这似乎是一个合乎逻辑的地方(至少对我来说),发布这些信息可能会帮助其他处于类似情况的人,尤其是BaSH程序员。
确保数字被视为10基数整数的另一种方法是使用printf。此命令指示printf将$num视为整数,并将其四舍五入到小数点后0位。
num="$(printf "%.0f" "$num")"
或者,如果你还想确保字符串中没有非数字字符,你可以这样做:
num="$(printf "%.0f" "${num//[!0-9]/}")"
这两个命令都将去掉前导零,并将十进制值四舍五入到最接近的整数。请注意,第一个(更简单的)解决方案适用于负数,但第二个解决方案不适用(它总是返回绝对值)。
请注意,printf向下取整,这意味着.01到0.5取整为0,而.51到.99取整为1。基本上,在这种情况下,向上取整与向下取整的区别在于printf向下取整0.5及以下。我提到这一点是因为0.5取整是一种更常见的做法。
现在,解决OP的具体场景。。。。将printf与awk组合使用,可以实现单独使用 print f这个 compare=$((${SEC}/(606024)) 也可以表示为 或 同时, 值=$((值+比较)) 可以计算为compare=$(awk -v sec=$SEC 'BEGIN { print int(sec/(60*60*24))}')
compare="$(printf "%.0f" "$(awk "BEGIN { print ( $SEC / ( 60 * 60 * 24 ) ) }")")"
value="$(printf "%.0f" "$(awk "BEGIN { print ( $value + $compare ) }")")"
算术展开表达式中不需要$
和{}
。它应该是这样的:
compare=$((SEC/(60*60*24)))
对于日期中的"mm"one_answers"dd"值,我使用以下技巧:
mm="1${date:5,2}" # where 5 is the offset to mm in the date
let mm=$mm-100 # turn 108 into 8, and 109 into 9