J'ai un fichier au nom de Build.number avec la valeur de contenu 12 que je dois incrémenter de +1. Alors j'ai essayé ça
BN=$($cat Build.number)
BN=$(($BN+1))
echo $BN >Build.number
mais ici j'obtiens la valeur 11 quand j'attends 1. Quelqu'un peut-il m'aider?
Le 0 en tête fait que Bash interprète la valeur comme une valeur octale ; 012 octal est 10 décimales, donc vous obtenez 11.
Pour forcer l'utilisation de décimales, ajoutez 10#
(tant que le nombre n'a pas de signe de tête):
BN=10#$(cat Build.number)
echo $((++BN)) > Build.number
Pour imprimer le numéro en utilisant au moins trois chiffres, utilisez printf
:
printf "%.3d\n" $((++BN)) > Build.number
bash
traite les constantes commençant par 0
comme des nombres octaux dans ses expressions arithmétiques, donc 011
est en fait 9
.
C'est en fait une exigence POSIX.
Certains autres shells comme mksh
ou zsh
l'ignorent (sauf en mode compatible POSIX) car ils gênent beaucoup plus souvent qu'il n'est utile.
Avec ksh93
, BN=011; echo "$(($BN))"
génère 9
, Mais echo "$((BN))"
génère 11.
Dans bash
, vous pouvez utiliser BN=$((10#$(<Build.number)))
, qui devrait fonctionner tant que le nombre ne commence pas par -
Ou +
.
Dans n'importe quel shell POSIX, vous pouvez empêcher qu'un nombre soit considéré comme octal en supprimant ses zéros de tête avec une combinaison de ${var#prefix}
et ${var%%suffix}
formes d'expansion:
BN=001002; BN=$(( ${BN#${BN%%[!0]*}} + 1 )); echo "$BN"
1003
Dans des coquilles qui supportent le ${var//pat/repl}
syntaxe, vous pouvez également le faire en lui ajoutant un 1
et en le soustrayant de 10^{number_of_digits}
:
BN=000012; BN=$(( 1$BN - 1${BN//?/0} )); echo "$BN"; BN=$((BN+1)); echo "$BN"
12
13
Cela fonctionne dans bash
, zsh
, ksh93
, mksh
et yash
.
Dans bash
, ksh93
et zsh
(mais pas dans yash
et mksh
), vous pouvez également utiliser le fortranish **
opérateur (exponentiation):
BN=000012; BN=$(( 1$BN - 10**${#BN} ))
Voici une fonction pour incrémenter une chaîne numérique. Il observe les zéros en tête et essaie de conserver le nombre de chiffres. Il n'utilise aucune variable, il ne nécessite donc aucune extension Shell pour déclarer des variables locales et ne pollue pas l'espace de noms des variables:
# $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 ))
}
Tests interactifs:
$ 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