我有一个名为 Build.number 的文件,其内容值012我需要将其增加+1。所以,我尝试了这个
BN=$($cat Build.number)
BN=$(($BN+1))
echo $BN >Build.number
但当我期待时,我得到的值是 11013。谁能帮我?
答案1
前导 0 导致 Bash将值解释为八进制值;八进制的 012 是十进制的 10,所以得到 11。
要强制使用小数,请添加10#
(只要数字没有前导符号):
BN=10#$(cat Build.number)
echo $((++BN)) > Build.number
要打印至少使用三位数字的数字,请使用printf
:
printf "%.3d\n" $((++BN)) > Build.number
答案2
bash
0
在其算术表达式中将以 开头的常量视为八进制数,011
实际上也是如此9
。
这实际上是 POSIX 的要求。
其他一些 shell 喜欢mksh
或zsh
忽略它(除非在 POSIX 兼容模式下),因为它造成的干扰远远超过了它的用处。
与ksh93
,BN=011; echo "$(($BN))"
输出9
, 但echo "$((BN))"
输出 11。
在 中bash
,您可以使用BN=$((10#$(<Build.number)))
,只要数字不以-
或开头,它就应该有效+
。
答案3
${var#prefix}
在任何 POSIX shell 中,您可以通过使用和扩展形式的组合去除数字的前导零来防止数字被视为八进制${var%%suffix}
:
BN=001002; BN=$(( ${BN#${BN%%[!0]*}} + 1 )); echo "$BN"
1003
在支持该语法的 shell 中,您还可以通过在前面添加 a并从 中减去它来${var//pat/repl}
实现:1
10^{number_of_digits}
BN=000012; BN=$(( 1$BN - 1${BN//?/0} )); echo "$BN"; BN=$((BN+1)); echo "$BN"
12
13
这适用于bash
、zsh
、ksh93
和mksh
。yash
在bash
, ksh93
and zsh
(但不是在yash
and mksh
)中,您还可以使用 fortranish**
运算符(求幂):
BN=000012; BN=$(( 1$BN - 10**${#BN} ))
答案4
这是一个递增数字字符串的函数。它观察前导零并尝试保留位数。它不使用变量,因此不需要任何 shell 扩展来声明局部变量,并且不会污染变量命名空间:
# $1 -- decimal string, possibly with leading zeros or sign
# $2 -- integer increment, no leading zeros.
incnumstr()
{
if [ $1 -lt 0 ] ; then
set -- $(incnumstr ${1#-} $((- $2)))
[ $1 -le 0 ] && printf "%s" ${1#-} \
|| printf "%s" -$1
return
fi
set -- ${1#-} $2 # strip leading minus from zero
[ $1 -eq 0 ] && printf "%s%0.*d" "$3" ${#1} $2 \
|| printf "%s%0.*d" "$3" ${#1} $(( ${1#${1%%[1-9]*}} + $2 ))
}
互动测试:
$ echo $(incnumstr 0 0)
0
$ echo $(incnumstr -0 0)
0
$ echo $(incnumstr 0 1)
1
$ echo $(incnumstr 0 -1)
-1
$ echo $(incnumstr 00 1)
01
$ echo $(incnumstr 00 -1)
-01
$ echo $(incnumstr -10 10)
00
$ echo $(incnumstr -10 11)
01
$ echo $(incnumstr -10 20)
10
$ echo $(incnumstr -10 99)
89
$ echo $(incnumstr -10 110)
100
$ echo $(incnumstr 100 -90)
010
$ echo $(incnumstr 100 -99)
001
$ echo $(incnumstr 100 -100)
000
$ echo $(incnumstr 100 -101)
-001
$ echo $(incnumstr 100 -1234)
-1134
$ echo $(incnumstr -0000 0)
0000
$ echo $(incnumstr -0000 1)
0001
$ echo $(incnumstr -0000 -2)
-0002