6

I have read about specifying "10#", but I don't think it's my case as I am not doing number comparison. I am trying to create an associative array in Bash, and the code worked fine until today (2021-02-08):

dailyData["$today"]="$todayData"

$today is a day in ISO format, $todayData is not relevant.
I am getting the error 2021-02-08: value too great for base (error token is "08").

Why does Bash interpret this date format as a number, where an arbitrary string does the job (associative array key)?
What if I wanted to use just "08" as dictionary key?

2 Answers 2

12

It's because dailyData is being automatically created as indexed array rather than an associative array. From man bash:

An indexed array is created automatically if any variable is assigned to using the syntax name[subscript]=value. The subscript is treated as an arithmetic expression that must evaluate to a number.

The issue goes away if you explicitly declare dailyData as an associative array:

$ declare -A dailyData[2021-02-08]="$todayData"

$ declare -p dailyData
declare -A dailyData=([2021-02-08]="" )
1
  • Oh thank you, I forgot to use declare -A either when adding values or before starting to do so like in @choroba's example. I also noticed that if you use a string as subscript (indexed array) it doesn't fail, but it sets the subscript to "0", eventually replacing older entries
    – Polizi8
    Commented Feb 8, 2021 at 12:04
8

I can't reproduce the problem with associative arrays:

#! /bin/bash
declare -A dailyData
today=2021-02-08
todayData=whatever
dailyData["$today"]="$todayData"

But, if I use normal arrays, i.e. declare -a (mind the case!) or no declaration at all, then I'm getting the error you mention. That's because the array index is interpreted as an arithmetic expression, so for 2021-02-07, it was just calculated as 2021 - 2 - 7 = 2012, but for 2021-02-08, the last number in the subtraction is invalid in octal.

7
  • 3
    and that last part of course means that e.g. 2021-03-06 would be taken as exactly the same index as 2021-02-07, even though they'd seem to work without errors.
    – ilkkachu
    Commented Feb 8, 2021 at 9:54
  • Thank you, I forgot declare -A. Any idea on why if a common word is used as subscript of an indexed array, it is evaluated to 0, without returning any error like "'word' is not a valid expression"?
    – Polizi8
    Commented Feb 8, 2021 at 12:10
  • @Polizi8, because it is a valid expression, one that refers to a variable by that name. E.g. foo=3; echo $((foo+4)) prints 7 in all shells I have, and Bash/ksh/Zsh even do that recursively, so foo="2*bar"; bar=3; echo $((foo+4)) prints 10. Bash's manual describes this: "Within an expression, shell variables may also be referenced by name without using the parameter expansion syntax." and "The value of a variable is evaluated as an arithmetic expression when it is referenced."
    – ilkkachu
    Commented Feb 8, 2021 at 12:31
  • @Polizi8, Actually, that behaviour is kinda scary if you take supposedly numeric values as input from a user. If they enter a name of a variable, they can force your script to use that, even if it's supposed to be something "hidden". Worse, Bash/ksh/Zsh also process any expansions, including command substitutions in array indices, even within variables used in arithmetic. So something like foo="a[\$(echo surprise >&2)]"; echo $((foo+4)) will run the echo and print surprise to stderr.
    – ilkkachu
    Commented Feb 8, 2021 at 12:36
  • @ilkkachu Yes but I am not talking about a variable: by running declare -a array[word]="value", "value" is associated to index "0", as shown by echo "${!array[*]}" and echo "${array[0]}". Why does "word" get converted to "0"? I have never declared "word" or "w", "o", "r", "d" as variables
    – Polizi8
    Commented Feb 8, 2021 at 14:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .