关联数组:错误“声明:-A:无效选项”

发布于 2024-11-08 06:27:00 字数 633 浏览 4 评论 0原文

我编写了一个在 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 的 man 中,它讨论了使用 -A 所以我认为它应该工作。

关联数组是使用以下命令创建的 声明 -A 名称

我可以通过打印 echo 'bash -version 的值来确认脚本正在使用正确的 bash 版本。

我可能做错了什么?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

怼怹恏 2024-11-15 06:27:00

以下似乎是使用 Homebrew 安装较新的 Bash 后 macOS 上的典型场景:

  • /bin/bash 是旧的 Bash,3.2
  • /usr/local/bin/bash是了解关联数组的新 Bash(4.0 或更高版本)
  • type bash 指向 /usr/local/bin/bashbash --version 是新的(因为它解析为 /usr/local/bin/bash --version

但是,带有 #!/bin/bash shebang 行的脚本使用 ./script 运行的将使用旧的 Bash (问题中的场景)。解决方案是:

  • 使用bash脚本调用脚本:将使用新的Bash。 缺点:你总是必须这样称呼它。
  • 将 shebang 行更改为 #!/usr/local/bin/bash缺点:在许多系统上,/usr/local/bin 中没有 Bash,并且您的脚本不再可移植。
  • 将 shebang 行更改为 #!/usr/bin/env bash这将使用 PATHbash code>,这应该是新的。这非常便携;唯一的缺点是你不知道具体会执行哪个 Bash。

另请参阅这些问答:

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:

凉月流沐 2024-11-15 06:27:00

确保在 shell 脚本顶部作为解释器调用的 bash 版本(#!/bin/bash 或其他)也是版本 4。如果您正在这样做:

bash --version

并且它为您提供了 v4 ,执行 which bash 来检查它的位置。

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.

Hello爱情风 2024-11-15 06:27:00

如果您想在 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

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
辞旧 2024-11-15 06:27:00

以下是如何在 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)

2023年,路径发生了变化。目前的一项是:

$ /opt/homebrew/bin/bash --version
GNU bash, version 5.2.15(1)-release (aarch64-apple-darwin22.1.0)
Copyright (C) 2022 Free Software Foundation, Inc.

Here is how to get the updated bash version on OS X, you should install brew and then 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)

In 2023, the path has changed. The current one is:

$ /opt/homebrew/bin/bash --version
GNU bash, version 5.2.15(1)-release (aarch64-apple-darwin22.1.0)
Copyright (C) 2022 Free Software Foundation, Inc.
蒗幽 2024-11-15 06:27:00
  1. 通过此 cmd 检查您当前使用的 shell:

    echo $SHELL
    

    例如,它可能会说 /bin/bash

  2. $SHELL 上运行 --version

    <前><代码>/bin/bash --版本

    它可能会输出类似GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin16)

    如果是版本 4 之前的版本,则必须升级。

  3. 检查您是否已有版本 4 的 bash shell。尝试运行:

    <前><代码>bash --版本

    如果是这样,您只需将默认 shell 更改为该 shell。

    您可以使用这些命令来执行此操作:

    sudo bash -c 'echo /usr/local/bin/bash >>> /etc/shell'
    须藤 chsh -s /usr/local/bin/bash
    

    第一个将 shell 添加到允许的 shell 中。第二个实际上更改了您的默认 shell。

  1. Check the current shell you are using with this cmd:

    echo $SHELL
    

    E.g. it could say /bin/bash

  2. Run --version on that $SHELL:

    /bin/bash --version
    

    It may output something like GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin16)

    If it is before version 4, you'll have to upgrade.

  3. 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.

如果没结果 2024-11-15 06:27:00

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

这将返回值“to meet you” ”。

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".

疯狂的代价 2024-11-15 06:27:00

旧的 BASH 版本不支持声明数组的 declare -A 语法。我建议使用这两种形式中的任何一种在 bash 中声明数组,以使其与生产系统的旧 bash 版本兼容:

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

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

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:

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

or

arr[0]=10
arr[1]=20
arr[2]=30
echo ${arr[@]}
喜你已久 2024-11-15 06:27:00

上面没有任何帮助我,所以我打开 /etc/shells 并更改了行
- /bin/bash/usr/local/bin/bash,然后重新加载
source /etc/shells 现在我可以享受 bash v4 的新可能性

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

蓬勃野心 2024-11-15 06:27:00

根据命令:

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”。将其与帮助命令中的用法字符串进行比较。看起来好像给定的机器不支持它。

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.

九局 2024-11-15 06:27:00

尝试使用不同的 shebang。在我的 Mac 上:

$ which bash
/usr/local/bin/bash

所以,这个脚本运行良好,生成“Hello World”:

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

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]}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文