Как выполнить итерацию целого числа, дополненного нулями, в bash?

Как выполнить итерацию целого числа, дополненного нулями, в bash?

Как выполнить итерацию строки в форме «[AZ][0-9]*» или, например: «A000001»?

Получив переменную, я разделяю:

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]*")

Однако когда я пытаюсь добавить 1:

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

Счетчик доходит до «000009» и возвращается к «000000».

И я присоединяюсь следующим образом:

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

А в отношении итерации Letter я думал использовать Associated Array? Или раскрытие фигурных скобок {A..Z}, но это уже совсем другой вопрос.

решение1

В bash, числа с ведущими нулями считаются восьмеричными. Чтобы заставить bashих считаться десятичными, можно добавить 10#префикс:

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

Или с bash 3.1 или выше, чтобы избежать разветвления:

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

(обратите внимание, что это не работает для отрицательных чисел, как 10#-010показано 10#0 - 010в bash, поэтому $((10#-10))и $((-10#-10))расширяются до -8).

Смотрите также:

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

Или:

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

Или:

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

решение2

Perl спешит на помощь:

perl -E '$x = "A001"; say $x++ for 1 .. 1002' 

Выход:

A001
A002
A003
A004
A005
A006
A007
A008
A009
A010
A011
...
A996
A997
A998
A999
B000
B001
B002

Оператор ++ обрабатывает как буквы, так и цифры.

решение3

По историческим причинам числовые операции в оболочках в стиле Bourne/POSIX обрабатывают целочисленные константы с ведущей 0цифрой как восьмеричные, а не как десятичные. Поэтому 08в арифметической операции есть синтаксическая ошибка, последующее значение 07равно 8, и 010эквивалентно 8.

Вы можете использовать обычную арифметику, а затем дополнять числа при печати с помощью printfвстроенной функции.

next_number=$(($current_number + 1))
printf -v padded_next_number %06d "$next_number"

Параметр специфичен -vдля printfbash; способ POSIX —

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

Вот еще один подход, который был полезен в исторических системах, не имевших команды printf, и все еще может быть полезен для производительности в немногих оболочках, не имеющих printfвстроенной команды. Вместо того, чтобы считать с 1, считайте с 1000001. Таким образом, ваши числа никогда не будут иметь начальных нулей. Когда вы используете число, отбросьте начальную 1цифру.

number=1000000
while … ; do
  number=$((number+1))
  echo "${number#1}"
done

Связанный контент