Bash 4 associative arrays: error “declare: -A: invalid option”

Multi tool use


Bash 4 associative arrays: error “declare: -A: invalid option”
I've written a script that uses associative arrays in bash (v 4).
It works fine on my local machine which is using 4.1.5(1)-release
.
4.1.5(1)-release
On the production machine, using 4.1.0(1)-release
the following line, which declares the assoc array, fails:
4.1.0(1)-release
declare -A uniqjars
with the message:
/script.sh: line 11: declare: -A: invalid option
declare: usage: declare [-afFirtx] [-p] [name[=value] ...]
I was under the impression this was a general bash 4 feature?
In the man for bash on the production machine it discusses using -A
so I assume it should work.
-A
Associative arrays are created using
declare -A name
.
declare -A name
I can confirm the script is using the right version of bash by printing out the value of echo 'bash -version
.
echo 'bash -version
What could I be doing wrong?
may be you're using an incorrect shebang?
– freethinker
May 18 '11 at 16:24
Correct, I was.
– Joel
May 18 '11 at 16:28
10 Answers
10
Make sure the version of bash being invoked as interpreter at the top of your shell script (#!/bin/bash
or whatever) is also version 4. If you're doing:
#!/bin/bash
bash --version
and it's giving you v4, do a which bash
to check it's location.
which bash
With
which bash
, I found I was not upgraded to bash 4. I used this link to upgrade the version on my MacBook Pro running Lion. YMMV– AWrightIV
Jan 31 '13 at 0:54
which bash
Bash 4 for OSX can also be obtained through brew. However,
/bin/bash
will need to be replaced by or symbolically linked to the version it installs.– Tom Sweeney
Aug 5 '15 at 17:13
/bin/bash
Here is a Workaround, if you want to use chars as array index with bash v3:
array=(
'hello::world.'
'nice::to meet you'
)
for index in "${array[@]}" ; do
KEY="${index%%::*}"
VALUE="${index##*::}"
echo "$KEY - $VALUE"
done
Output:
hello - world.
nice - to meet you
Welcome to Stack Exchange. You should not add comments or questions as answer, they will be most likely deleted. If you have a question please ask one but make sure to read How to Ask first. To critique or request clarification from an author, leave a comment below their post once you have sufficient reputation. Deleted post might lead to bad consequences REF
– bummi
Aug 1 '13 at 11:41
So it appears this just splits the string, using
::
as the center - string='hello::world' && LEFT="${string%%::*}" && RIGHT="${string##*::}" && echo $LEFT "<>" $RIGHT
- You still can't lookup a value by key.– jgraup
Apr 10 '16 at 12:34
::
string='hello::world' && LEFT="${string%%::*}" && RIGHT="${string##*::}" && echo $LEFT "<>" $RIGHT
The following seems to be a typical scenario on macOS after installing a newer Bash with Homebrew:
/bin/bash
/usr/local/bin/bash
type bash
/usr/local/bin/bash
bash --version
/usr/local/bin/bash --version
However, scripts with a #!/bin/bash
shebang line that are run with ./script
will use the old Bash (the scenario in the question). Solutions are:
#!/bin/bash
./script
bash script
#!/usr/local/bin/bash
/usr/local/bin
#!/usr/bin/env bash
bash
PATH
See also these Q&A:
Heh. This is indeed directly on-point.
– Charles Duffy
Oct 3 '17 at 20:59
Here is how to get the updated bash
version on OS X, you should install brew
and then bash
.
bash
brew
bash
$ /bin/bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin14)
$ brew install bash
... install
$ /usr/local/bin/bash --version
GNU bash, version 4.3.46(1)-release (x86_64-apple-darwin14.5.0)
meigrafd's answer solved my problem, so if using an incorrect shebang or still on bash version 3 the following allowed me to return a value based on it's associated key:
array=(
'hello::world.'
'nice::to meet you'
)
for index in "${array[@]}" ; do
KEY="${index%%::*}"
VALUE="${index##*::}"
if [ "$KEY" == "nice" ]; then
echo "$VALUE"
break
fi
done
This will return the value "to meet you".
Check the current shell you are using with this cmd:
echo $SHELL
E.g. it could say /bin/bash
/bin/bash
Run --version
on that $SHELL
:
--version
$SHELL
/bin/bash --version
It may output something like GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin16)
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin16)
If it is before version 4, you'll have to upgrade.
Check if you already have a bash shell with version 4. Try running:
bash --version
If so, you just need to change your default shell to that shell.
You can use these cmds to do so:
sudo bash -c 'echo /usr/local/bin/bash >> /etc/shells'
sudo chsh -s /usr/local/bin/bash
The first adds the shell to the allowed shells. The second actually changes your default shell.
Old BASH version didn't support declare -A
syntax of declaring arrays. I suggest using either of these 2 forms to declare arrays in bash to make it compatible with older bash version of your production system:
declare -A
arr=( '10' '20' '30' )
echo ${arr[@]}
or
arr[0]=10
arr[1]=20
arr[2]=30
echo ${arr[@]}
Nothing above helped me, so I opened /etc/shells and changed the line
- /bin/bash
to /usr/local/bin/bash
, and then reloaded it with source /etc/shells
and now I can enjoy new possibilities of v4 of bash
/bin/bash
/usr/local/bin/bash
source /etc/shells
Per the command:
help declare
declare: declare [-aAfFgilnrtux] [-p] [name[=value] ...]
Set variable values and attributes.
Declare variables and give them attributes. If no NAMEs are given,
display the attributes and values of all variables.
Options which are set attributes:
-a to make NAMEs indexed arrays (if supported)
-A to make NAMEs associative arrays (if supported)
Notice lowercase "-a" and uppercase "-A" are "(if supported)". Also if you look at the posted error message for declare usage:
/script.sh: line 11: declare: -A: invalid option
declare: usage: declare [-afFirtx] [-p] [name[=value] ...]
The given options are "[-afFirtx]" showing to use a lowercase "-a" but no uppercase "-A". Compare that to the usage string from the help command. It looks as if it's just not supported on the given machine.
Try using a different shebang. On my Mac:
$ which bash
/usr/local/bin/bash
So, this script runs fine, producing "Hello World":
#!/usr/local/bin/bash
declare -A assoc
assoc[hello]="Hello World"
echo ${assoc[hello]}
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
I'm guessing that since I upgraded from bash 3 to 4 on the machine for some reason it's picking up the old declare function from bash3 ?
– Joel
May 18 '11 at 16:13