
Como iterar uma string com o formato "[AZ][0-9]*" Ou por exemplo: "A000001"?
Depois de receber a variável eu divido:
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]*")
No entanto, quando tento adicionar 1:
# add 1 & keep all leading zeros "000001"
next_number=$(printf %06d $(($current_number + 1)))
Conta até "000009" e volta para "000000".
E eu associo da seguinte forma:
next_=$(echo "$current_letter$next_number")
E em relação à iteração Letter eu estava pensando em usar um Associated Array? Ou cinta expansão {A..Z}
, mas essa é uma questão totalmente diferente.
Responder1
Em bash
, números com zeros à esquerda são considerados octais. Para forçar bash
a considerá-los como decimais, você pode adicionar um 10#
prefixo:
next_number=$(printf %06d "$((10#$current_number + 1))")
Ou com o bash 3.1 ou superior, para evitar a bifurcação:
printf -v next_number %06d "$((10#$current_number + 1))"
(observe que não funciona para números negativos como 10#-010
é visto 10#0 - 010
em bash
, então ambos $((10#-10))
e $((-10#-10))
expandem para -8
).
Veja também:
$ printf 'A%06d\n' {5..12}
A000005
A000006
A000007
A000008
A000009
A000010
A000011
A000012
Ou:
$ printf '%s\n' {A..C}{00008..00012}
A00008
A00009
A00010
A00011
A00012
B00008
B00009
B00010
B00011
B00012
C00008
C00009
C00010
C00011
C00012
Ou:
$ seq -f A%06g 5 12
A000005
A000006
A000007
A000008
A000009
A000010
A000011
A000012
Responder2
Perl para o resgate:
perl -E '$x = "A001"; say $x++ for 1 .. 1002'
Saída:
A001
A002
A003
A004
A005
A006
A007
A008
A009
A010
A011
...
A996
A997
A998
A999
B000
B001
B002
O operador ++ lida com letras e números.
Responder3
Por razões históricas, as operações numéricas em shells estilo Bourne/POSIX analisam constantes inteiras com um 0
dígito inicial como octal em vez de decimal. Portanto, 08
em uma operação aritmética há um erro de sintaxe, o sucessor de 07
é 8 e 010
é equivalente a 8
.
Você pode usar aritmética normal e preencher os números ao imprimi-los com o printf
integrado.
next_number=$(($current_number + 1))
printf -v padded_next_number %06d "$next_number"
A -v
opção printf
é específica do bash; a maneira POSIX é
next_number=$(($current_number + 1))
padded_next_number=$(printf %06d "$next_number")
Aqui está outra abordagem que foi útil em sistemas históricos que não possuíam um printf
comando e ainda pode ser útil para desempenho nos poucos shells que não possuem printf
um comando integrado. Em vez de contar a partir de 1, conte a partir de 1.000.001. Dessa forma, seus números nunca precisarão ter zeros à esquerda. Ao usar o número, retire o 1
dígito inicial.
number=1000000
while … ; do
number=$((number+1))
echo "${number#1}"
…
done