
¿Cómo se itera una cadena con la forma "[AZ][0-9]*" o, por ejemplo: "A000001"?
Después de recibir la variable dividí:
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]*")
Sin embargo, cuando intento agregar 1:
# add 1 & keep all leading zeros "000001"
next_number=$(printf %06d $(($current_number + 1)))
Cuenta hasta "000009" y retrocede hasta "000000".
Y me uno de la siguiente manera:
next_=$(echo "$current_letter$next_number")
¿Y con respecto a la iteración Letter, estaba pensando en usar una matriz asociada? O expansión de llaves {A..Z}
, pero esa es una cuestión completamente diferente.
Respuesta1
En bash
, los números con ceros a la izquierda se consideran octales. Para forzar bash
a considerarlos como decimales, puedes añadir un 10#
prefijo:
next_number=$(printf %06d "$((10#$current_number + 1))")
O con bash 3.1 o superior, para evitar la bifurcación:
printf -v next_number %06d "$((10#$current_number + 1))"
(tenga en cuenta que no funciona para números negativos como 10#-010
se ve 10#0 - 010
en bash
, por lo que ambos $((10#-10))
se $((-10#-10))
expanden a -8
).
Ver también:
$ printf 'A%06d\n' {5..12}
A000005
A000006
A000007
A000008
A000009
A000010
A000011
A000012
O:
$ printf '%s\n' {A..C}{00008..00012}
A00008
A00009
A00010
A00011
A00012
B00008
B00009
B00010
B00011
B00012
C00008
C00009
C00010
C00011
C00012
O:
$ seq -f A%06g 5 12
A000005
A000006
A000007
A000008
A000009
A000010
A000011
A000012
Respuesta2
Perl al rescate:
perl -E '$x = "A001"; say $x++ for 1 .. 1002'
Producción:
A001
A002
A003
A004
A005
A006
A007
A008
A009
A010
A011
...
A996
A997
A998
A999
B000
B001
B002
El operador ++ maneja tanto letras como números.
Respuesta3
Por razones históricas, las operaciones numéricas en shells estilo Bourne/POSIX analizan constantes enteras con un 0
dígito inicial como octal en lugar de decimal. Entonces 08
en una operación aritmética hay un error de sintaxis, el sucesor de 07
es 8, y 010
equivale a 8
.
Puede usar aritmética normal y luego rellenar los números al imprimirlos con el printf
incorporado.
next_number=$(($current_number + 1))
printf -v padded_next_number %06d "$next_number"
La -v
opción printf
es específica de bash; la forma POSIX es
next_number=$(($current_number + 1))
padded_next_number=$(printf %06d "$next_number")
Aquí hay otro enfoque que fue útil en sistemas históricos que no tenían un printf
comando y aún puede ser útil para el rendimiento en los pocos shells que no lo tienen printf
incorporado. En lugar de contar desde 1, cuente desde 1000001. De esa manera, sus números nunca tendrán que tener ceros a la izquierda. Cuando uses el número, quita el 1
dígito inicial.
number=1000000
while … ; do
number=$((number+1))
echo "${number#1}"
…
done