De acordo com as Leis 12.965/2014 e 13.709/2018, que regulam o uso da Internet e o tratamento de dados pessoais no Brasil, ao me inscrever na newsletter do portal DICAS-L, autorizo o envio de notificações por e-mail ou outros meios e declaro estar ciente e concordar com seus Termos de Uso e Política de Privacidade.

Octal é a Vovozinha

Colaboração: Paulo Roberto Bagatini

Data de Publicação: 26 de maio de 2014

Ninguém está livre de ser pego desprevenido pela notação numérica do BASh:

  $ echo $((010+070)) # 1 
  64 
  $ echo $(( 10+070)) # 2 
  66 
  $ echo $((010+ 70)) # 3 
  78 
  $ echo $((010+ 90)) # 4 
  98 
  $ echo $(( 10+090)) # 5 
  bash: 10+090: valor muito grande para esta base de numeração (token com erro é "090") 

QUÊ BASE de numeração, tchê?

Octal, é claro. O BASh considera números que iniciam com zero como estando na base 8. Se estão na base 8, não podem ter dígitos maiores que 7 ;-)

Na dica Bashes Numéricas no BASh, foi mostrado que o BASh trabalha nativa e simultaneamente com bases numéricas diferentes:

  • no caso 1 acima, somando 2 números octais
  • no caso 2, 10 em decimal e 70 em octal
  • no caso 3, 10 em octal e 70 em decimal
  • no caso 4, 10 em octal e 90 em decimal
  • no caso 5, 10 em decimal e 90 em octal, o que provoca um erro, uma vez que não temos o dígito 9 nessa base.

Quando a operação ocorre interativamente e com números, no "estilo calculadora", basta não usar o zero cabide, e tudo estará resolvido:

  $ echo $((10+70)) 
  80 
  
  $ echo $((10+90)) 
  100 

Mas às vezes os números estão escondidos em variáveis. Às vezes a quantidade de dígitos foi padronizada com o comando printf, ou os valores foram gerados a partir da expansão de chaves (brace expansion) {000..010} ou com o comando seq. Outras vezes, simplesmente nos damos conta que uma variável que não era pra ter nada de anormal apareceu com um zero na frente do conteúdo, e agora temos que ficar implantando patches no nosso algoritmo para driblar essa idiossincrasia do nosso amigo BASh :-p

Em vez de apelar para o sed ou tr para tirar os zeros cabide salvando o resultado em uma variável auxiliar, podemos usar a notação explícita de bases numéricas do BASh e deixar bem claro para o shell que SIM, estamos trabalhando na base decimal! Pombas...

  $ a=11 
  $ b=209 
  $ echo $((a+b)) 
  # OK 
  
  $ a=$(printf %04d 11)  # 0011 
  $ b=$(printf %06d 209) # 000209 
  $ echo $((a+b)) 
  bash: 000209: valor muito grande para esta base de numeração (token com erro é "000209") 
  # Ops... 
  
  $ echo $((10#$a+10#$b)) 
  220 
  # OK novamente 

Observem a necessidade de deixar explícito também o que é variável e o que é dígito, quando usamos a notação explícita de base numérica:

  $ echo $((10#a+10#b)) 
  bash: 10#a: valor muito grande para esta base de numeração (token com erro é "10#a") 

Adicionar comentário

* Campos obrigatórios
5000
Powered by Commentics

Comentários (1)

Avatar
Novo

Dica muito boa essa Bagatini, muito obrigado, acabei de aplicar hoje em um script que precisava comparar o dia atual que vinha com 0 na frente.



Veja a relação completa dos artigos de Paulo Roberto Bagatini