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

Multi tool use
Multi tool use
The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP


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?





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





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.

wVCS20443,PzsgA3POc5 7,8AcL,U 4ZHCCxYx,pRTtnuN44fpgf z91bW04wfGwog 75
mn 32GxvaiWrJBKUk9x,pI4mM08w qi90

Popular posts from this blog

Keycloak server returning user_not_found error when user is already imported with LDAP

PHP parse/syntax errors; and how to solve them?

415 Unsupported Media Type while sending json file over REST Template