Como iterar um inteiro preenchido com zero no bash?

6

Como um itera uma string com o formato "[A-Z] [0-9] *" Ou por exemplo: "A000001"?

Depois de receber a variável, 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 para "000009" e retorna para "000000".

E eu participo da seguinte forma:

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

E no que diz respeito à iteração da letra, eu estava pensando em usar um array associado? Ou ajuste a expansão {A..Z} , mas essa é uma questão totalmente diferente.

    
por jmunsch 18.11.2014 / 16:41

3 respostas

13

Em bash , os números com zeros à esquerda são considerados octal.

Você pode usar:

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

Para informar bash para considerá-lo como decimal.

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
    
por 18.11.2014 / 17:31
5

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.

    
por 18.11.2014 / 17:00
1

Por razões históricas, operações numéricas em shells ao estilo Bourne / POSIX analisam constantes inteiras com um dígito 0 inicial como octal em vez de decimal. Portanto, 08 em uma operação aritmética é um erro de sintaxe, o sucessor de 07 é 8 e 010 é equivalente a 8 .

Você pode usar a aritmética normal e, em seguida, preencher os números ao imprimi-los com o printf incorporado.

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

A opção -v para printf é específica do bash; o modo 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 tinham o comando printf , e ainda pode ser útil para o desempenho nos poucos shells que não têm printf como um builtin. Em vez de contar a partir de 1, conte a partir de 1000001. Dessa forma, seus números nunca terão zeros à esquerda. Quando você usa o número, retire o primeiro dígito 1 .

number=1000000
while … ; do
  number=$((number+1))
  echo "${number#1}"
  …
done
    
por 20.11.2014 / 03:54