Bash – How to iterate a zero padded integer in bash

arithmeticbashshell

How does one iterate a string with the form "[A-Z][0-9]*" Or for example: "A000001"?

After receiving the variable I split:

current_=$(mysql -h"$mysqlhost" -u"$mysqluser" -p"$PASS" "$DBNAME" -se "SELECT current_ FROM $GLOBALDB;")
current_number=$(echo $current_ | grep -oh "[0-9]*")
current_letter=$(echo $current_ | grep -oh "[A-Z]*")

However when I try to add 1:

# add 1 & keep all leading zeros "000001"
next_number=$(printf %06d $(($current_number + 1)))

It counts to "000009" and rolls back over to "000000".

And I join as follows:

next_=$(echo "$current_letter$next_number")

And in regards to the Letter iteration I was thinking of using an Associated Array? Or brace expansion {A..Z}, but that is a whole different question.

Best Answer

In bash, numbers with leading zeros are considered as octal. To force bash to consider them as decimal, you can add a 10# prefix:

next_number=$(printf %06d "$((10#$current_number + 1))")

Or with bash 3.1 or above, to avoid the forking:

printf -v next_number %06d "$((10#$current_number + 1))"

(note that it doesn't work for negative numbers as 10#-010 is seen as 10#0 - 010 in bash, so both $((10#-10)) and $((-10#-10)) expand to -8).

See also:

$ printf 'A%06d\n' {5..12}
A000005
A000006
A000007
A000008
A000009
A000010
A000011
A000012

Or:

$ printf '%s\n' {A..C}{00008..00012}
A00008
A00009
A00010
A00011
A00012
B00008
B00009
B00010
B00011
B00012
C00008
C00009
C00010
C00011
C00012

Or:

$ seq -f A%06g 5 12
A000005
A000006
A000007
A000008
A000009
A000010
A000011
A000012
Related Question