web-dev-qa-db-ja.com

Bash 4連想配列:エラー「宣言:-A:無効なオプション」

Bashで連想配列を使用するスクリプトを作成しました(v 4)。

4.1.5(1)-releaseを使用しているローカルマシンで正常に動作します。

実動マシンでは、4.1.0(1)-releaseを使用して、assoc配列を宣言する次の行が失敗します。

declare -A uniqjars

メッセージ付き:

/script.sh: line 11: declare: -A: invalid option
declare: usage: declare [-afFirtx] [-p] [name[=value] ...]

これは一般的なbash 4の機能であるという印象を受けましたか?

本番マシンでのbashの男性では、-Aの使用について説明しているので、should workと仮定します。

連想配列は、declare -A nameを使用して作成されます。

echo 'bash -versionの値を出力することにより、スクリプトが正しいバージョンのbashを使用していることを確認できます。

何が間違っているのでしょうか?

49
Joel

シェルスクリプトの上部でインタープリターとして起動されているbashのバージョンを確認してください(#!/bin/bashまたは何でも)はバージョン4でもあります。

bash --version

v4を提供しているので、which bash場所を確認します。

34
Richard H

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
28
meigrafd

以下は、Homebrewで新しいBashをインストールした後のmacOSの典型的なシナリオのようです:

  • /bin/bashは古いBash、3.2です
  • /usr/local/bin/bashは、連想配列(4.0以降)を認識する新しいBashです
  • type bash/usr/local/bin/bashを指し、bash --versionは新しいものです(/usr/local/bin/bash --versionに解決されるため)

ただし、#!/bin/bashで実行される./script Shebang行を持つスクリプトは、古いBashを使用します(問題のシナリオ)。ソリューションは次のとおりです。

  • bash scriptでスクリプトを呼び出します。新しいBashが使用されます。 欠点:常にそのように呼び出す必要があります。
  • Shebang行を#!/usr/local/bin/bashに変更します。 欠点:多くのシステムでは、/usr/local/binにBashがなく、スクリプトは移植できなくなりました。
  • Shebang行を#!/usr/bin/env bashに変更します。これは、bashの最初のPATHを使用します。新しいものでなければなりません。これはかなり移植性があります。唯一の欠点は、どのBashが実行されるか正確にわからないことです。

これらのQ&Aも参照してください。

18
Benjamin W.
  1. このcmdで使用している現在のシェルを確認します。

    _echo $Shell
    _

    例えば。 _/bin/bash_と言えます

  2. その_--version_で_$Shell_を実行します。

    _/bin/bash --version
    _

    GNU bash, version 3.2.57(1)-release (x86_64-Apple-darwin16)のようなものを出力するかもしれません

    バージョン4より前の場合は、アップグレードする必要があります。

  3. バージョン4のbashシェルが既にあるかどうかを確認します。実行してみてください:

    _bash --version
    _

    その場合、デフォルトのシェルをそのシェルに変更するだけです。

    これらのコマンドを使用して、次のことができます。

    _Sudo bash -c 'echo /usr/local/bin/bash >> /etc/shells'
    Sudo chsh -s /usr/local/bin/bash
    _

    最初は、許可されたシェルにシェルを追加します。 2番目は実際にデフォルトのシェルを変更します。

8
Tyler

OS Xで更新された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)
7
khancell

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

これは、「あなたに会う」という値を返します。

6
KeithJ

上記のことは何も助けにならなかったので、/ etc/shellsを開いて行を変更しました-/bin/bashから/usr/local/bin/bash、それからsource /etc/shellsそして今、私はbashのv4の新しい可能性を楽しむことができます

3
Mihey Mik

古いBASHバージョンは、配列宣言のdeclare -A構文をサポートしていませんでした。これらの2つの形式のいずれかを使用してbashで配列を宣言し、運用システムの古いbashバージョンと互換性を持たせることをお勧めします。

arr=( '10' '20' '30' )
echo ${arr[@]}

または

arr[0]=10
arr[1]=20
arr[2]=30
echo ${arr[@]}
2
anubhava

コマンドごと:

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」と大文字の「-A」は「(サポートされている場合)」であることに注意してください。また、使用を宣言するために投稿されたエラーメッセージを見ると:

/script.sh: line 11: declare: -A: invalid option
declare: usage: declare [-afFirtx] [-p] [name[=value] ...]

指定されたオプションは、「[-afFirtx]」で、小文字の「-a」を使用し、大文字の「-A」は使用しないことを示しています。これをhelpコマンドの使用法文字列と比較してください。特定のマシンでサポートされていないように見えます。

1

別のシバンを使用してみてください。私のMacの場合:

$ which bash
/usr/local/bin/bash

したがって、このスクリプトは問題なく実行され、「Hello World」を生成します。

#!/usr/local/bin/bash
declare -A assoc
assoc[hello]="Hello World"
echo ${assoc[hello]}
0
Khanan