Bash 4 ассоциативных массива: ошибка "объявить: -A: недопустимый параметр"
Я написал script, который использует ассоциативные массивы в bash (v 4).
Он отлично работает на моей локальной машине, которая использует 4.1.5(1)-release
.
На рабочей машине, используя 4.1.0(1)-release
, следующая строка, объявляющая массив-член, терпит неудачу:
declare -A uniqjars
с сообщением:
/script.sh: line 11: declare: -A: invalid option
declare: usage: declare [-afFirtx] [-p] [name[=value] ...]
У меня сложилось впечатление, что это была общая функция bash 4?
В man для bash на производственной машине обсуждается использование -A
, поэтому я предполагаю, что он должен работать.
Ассоциативные массивы создаются с использованием declare -A name
.
Я могу подтвердить, что script использует правильную версию bash, выписав значение echo 'bash -version
.
Что я могу делать неправильно?
Ответы
Ответ 1
Убедитесь, что версия bash вызывается как интерпретатор в верхней части оболочки script (#!/bin/bash
или что-то еще) также версия 4. Если вы делаете:
bash --version
и он даст вам v4, выполните which bash
, чтобы проверить его местоположение.
Ответ 2
Вот временное решение, если вы хотите использовать символы в качестве индекса массива с помощью bash v3:
array=(
'hello::world.'
'nice::to meet you'
)
for index in "${array[@]}" ; do
KEY="${index%%::*}"
VALUE="${index##*::}"
echo "$KEY - $VALUE"
done
Вывод:
hello - world.
nice - to meet you
Ответ 3
Ниже приведен типичный сценарий для macOS после установки новой версии Bash с Homebrew:
-
/bin/bash
это старый Bash, 3.2 -
/usr/local/bin/bash
- это новый Bash, который знает об ассоциативных массивах (4.0 или новее) -
type bash
указывает на /usr/local/bin/bash
а bash --version
является новым (поскольку он разрешается в /usr/local/bin/bash --version
)
Однако сценарии со строкой #!/bin/bash
./script
#!/bin/bash
, которые запускаются с помощью ./script
будут использовать старый Bash (сценарий, о котором идет речь). Решения:
- Вызовите скрипт с помощью скрипта
bash script
: будет использован новый Bash. Недостаток: вы всегда должны называть это так. - Измените строку shebang на
#!/usr/local/bin/bash
. Недостаток: во многих системах нет Bash в /usr/local/bin
и ваш скрипт больше не является переносимым. - Измените строку shebang на
#!/usr/bin/env bash
. Это будет использовать первый bash
в вашем PATH
, который должен быть новым. Это довольно портативный; Единственным недостатком является то, что вы точно не знаете, какой Bash будет выполнен.
Смотрите также эти вопросы и ответы:
Ответ 4
-
Проверьте текущую оболочку, которую вы используете с этим cmd:
echo $SHELL
например. он мог бы сказать /bin/bash
-
Запустите --version
на этом $SHELL
:
/bin/bash --version
Он может выводить что-то вроде GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin16)
Если это до версии 4, вам нужно будет обновить.
-
Убедитесь, что у вас уже есть оболочка bash с версией 4. Попробуйте запустить:
bash --version
Если это так, вам просто нужно изменить оболочку по умолчанию на эту оболочку.
Вы можете использовать эти cmds для этого:
sudo bash -c 'echo /usr/local/bin/bash >> /etc/shells'
sudo chsh -s /usr/local/bin/bash
Первое добавляет оболочку к разрешенным оболочкам. Второй фактически изменяет вашу оболочку по умолчанию.
Ответ 5
Вот как получить обновленную версию bash
на OS X, вы должны установить 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)
Ответ 6
meigrafd ответ решил мою проблему, поэтому, если вы использовали неверный shebang или еще на bash версии 3, это позволило мне вернуть значение на основе связанного с ним ключа:
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
Это вернет значение "встретить вас".
Ответ 7
В старой версии BASH не поддерживается синтаксис declare -A
объявления массивов. Я предлагаю использовать любую из этих двух форм для объявления массивов в BASH, чтобы сделать его совместимым со старой версией BASH вашей производственной системы:
arr=( '10' '20' '30' )
echo ${arr[@]}
или
arr[0]=10
arr[1]=20
arr[2]=30
echo ${arr[@]}
Ответ 8
Ничто не помогло мне, поэтому я открыл /etc/shells и изменил строку
- /bin/bash
до /usr/local/bin/bash
, а затем перезагрузите его
source /etc/shells
, и теперь я могу наслаждаться новыми возможностями v4 bash
Ответ 9
За команду:
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)
Обратите внимание, что строчные буквы "-a" и "upper" "-A" являются "(если поддерживается)". Также, если вы посмотрите на сообщение об ошибке для объявления использования:
/script.sh: line 11: declare: -A: invalid option
declare: usage: declare [-afFirtx] [-p] [name[=value] ...]
Указанные параметры: "[-afFirtx]", показывающий использование строчной буквы "-a", но без прописных букв "-A". Сравните это с строкой использования из команды help. Похоже, что он просто не поддерживается на данной машине.
Ответ 10
Попробуйте использовать другой shebang. На моем Mac:
$ which bash
/usr/local/bin/bash
Итак, этот script работает отлично, создавая "Hello World":
#!/usr/local/bin/bash
declare -A assoc
assoc[hello]="Hello World"
echo ${assoc[hello]}