
Как выполнить итерацию строки в форме «[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
для printf
bash; способ 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