¿Por qué piensa bash: 016 + 1 = 15?

60

¿Alguien puede explicarme por qué un número con un 0 inicial da este comportamiento divertido?

#!/bin/bash
NUM=016 
SUM=$((NUM + 1)) 
echo "$NUM + 1 = $SUM"

Imprimirá:

016 + 1 = 15

DeltaLima
fuente
3
Psst: printf "%03d\n" 10es completamente utilizable en bash para obtener un cero a la izquierda para nombres de archivos y demás .
Squeezy
@Squeezy Gracias, pero esa parte ya estaba funcionando. El problema real no era obtener un nombre de archivo con un 0. inicial. Descubría cuál era el nombre de archivo con el número más alto y luego creaba el siguiente en la secuencia, utilizando printf "prefijo-% 03d.tif" $ SUM.
DeltaLima
8
Tenga en cuenta que podría haberlo resuelto usted mismo simplemente haciendo estoecho $((016))
Mehrdad el
2
Para su información, esto es cierto en muchos lenguajes de programación: C, C ++, Javascript.
Paul Draper

Respuestas:

128

El malentendido es que los números no significan lo que esperas.

Un cero a la izquierda denota un número con base 8. Es decir, 016es igual a 8#16. Si desea mantener el cero inicial, entonces lo necesita 10#016.

> num=016
> echo $((num))
14
> echo $((10#$num))
16
Hauke ​​Laging
fuente
23
Hay 10 tipos de personas en el mundo. Aquellos que entienden binario, aquellos que no, aquellos que no esperaban una broma de base 8 y otros 5 tipos de personas.
Jon Story
42

Porque:

~$ echo $((NUM))
14

si el número comienza con 0, se considera un valor octal y 16 en octal es 14 en decimal.

fredtantini
fuente
2
Eso tiene un sentido perfecto y explica por qué mi script estaba sobrescribiendo mis archivos antiguos :-(
DeltaLima