web-dev-qa-db-fra.com

Comment incrémenter la valeur d'une variable (décimale) (avec zéro non significatif) de +1?

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?

13
Naik

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
32
Stephen Kitt

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 +.

18

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} ))
4
mosvy

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
0
Kaz