Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

On the production machine, using 4.1.0(1)-release the following line, which declares the assoc array, fails:

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.

Associative arrays are created using declare -A name.

I can confirm the script is using the right version of bash by printing out the value of echo 'bash -version.

What could I be doing wrong?

like image 484
Joel Avatar asked May 18 '11 16:05

Joel


2 Answers

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:

bash --version

and it's giving you v4, do a which bash to check it's location.

like image 57
Richard H Avatar answered Nov 16 '22 02:11

Richard H


The following seems to be a typical scenario on macOS after installing a newer Bash with Homebrew:

  • /bin/bash is the old Bash, 3.2
  • /usr/local/bin/bash is the new Bash that knows about associative arrays (4.0 or newer)
  • type bash points to /usr/local/bin/bash and bash --version is the new one (because it resolves to /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:

  • Call the script with bash script: the new Bash will be used. Disadvantage: you always have to call it like that.
  • Change the shebang line to #!/usr/local/bin/bash. Disadvantage: on many systems, there is no Bash in /usr/local/bin and your script isn't portable any longer.
  • Change the shebang line to #!/usr/bin/env bash. This will use the first bash in your PATH, which should be the new one. This is pretty portable; the only downside is that you don't know exactly which Bash will be executed.

See also these Q&A:

  • What is the difference between "#!/usr/bin/env bash" and "#!/usr/bin/bash"?
  • Why is #!/usr/bin/env bash superior to #!/bin/bash?
  • Why is it better to use “#!/usr/bin/env NAME” instead of “#!/path/to/NAME” as my shebang? on Unix & Linux
like image 52
Benjamin W. Avatar answered Nov 16 '22 01:11

Benjamin W.