Подтвердить что ты не робот

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.

Что я могу делать неправильно?

4b9b3361

Ответ 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]}