web-dev-qa-db-ja.com

(10進)変数の値を(先頭にゼロを付けて)+1する方法は?

Build.numberという名前のファイルにコンテンツ値12があり、+ 1する必要があります。だから、私はこれを試しました

BN=$($cat Build.number)
BN=$(($BN+1))
echo $BN >Build.number

しかし、ここでは1を期待しているときに値11を取得しています。誰か助けてもらえますか?

13
Naik

先頭の0により、Bashは 値を8進値として解釈します ; 012の8進数は10の10進数なので、11になります。

10進数の使用を強制するには、10#を追加します(数値に先行符号がない限り)。

BN=10#$(cat Build.number)
echo $((++BN)) > Build.number

少なくとも3桁を使用して数値を出力するには、printfを使用します。

printf "%.3d\n" $((++BN)) > Build.number
32
Stephen Kitt

bashは、_0_で始まる定数を算術式で8進数として扱うため、_011_は実際には_9_です。

これは実際にはPOSIXの要件です。

mkshzshのような他のいくつかのシェルは、それが役に立つよりもずっと頻繁に邪魔になるので、それを無視します(POSIX準拠モードでない限り)。

_ksh93_の場合、BN=011; echo "$(($BN))"は_9_を出力しますが、echo "$((BN))"は11.を出力します。

bashでは、BN=$((10#$(<Build.number)))を使用できます。これは、数値が_-_または_+_で始まらない限り機能します。

18

どのPOSIXシェルでも、${var#prefix}${var%%suffix}の拡張形式の組み合わせで先行ゼロを取り除いて、数値が8進数と見なされるのを防ぐことができます。

BN=001002; BN=$(( ${BN#${BN%%[!0]*}} + 1 )); echo "$BN"
1003

${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

これはbashzshksh93mkshおよびyashで機能します。

bashksh93およびzshyashおよびmkshは除く)では、fortranish **演算子も使用できます(べき乗):

BN=000012; BN=$(( 1$BN - 10**${#BN} ))
4
mosvy

数値文字列をインクリメントする関数を次に示します。先行ゼロを監視し、桁数を維持しようとします。変数を使用しないため、ローカル変数を宣言するためのシェル拡張は必要なく、変数の名前空間を汚染しません。

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