我已经编写了一个在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
,因此我认为它应该起作用。
关联数组是使用
declare -A name
。
我可以通过打印出echo 'bash -version
的值来确认脚本使用的是正确的bash版本。
我可能做错了什么?
请确保在shell脚本顶部(#!/bin/bash
或其他名称)作为解释器调用的bash的版本也为版本4。如果正在执行:
bash --version
并且它给您v4,执行which bash
检查它的位置。
如果您想将字符用作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
以下似乎是使用Homebrew安装更新的Bash之后在macOS上的典型场景:
/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
shebang行的脚本将使用旧的Bash(问题中的方案)。解决方案是:
bash script
调用脚本:将使用新的Bash。 缺点:您总是必须这样称呼它。#!/usr/local/bin/bash
。 缺点:在许多系统上,/usr/local/bin
中没有Bash,并且您的脚本不再可移植。#!/usr/bin/env bash
。这将使用bash
中的第一个PATH
,它应该是新的。这是非常可移植的。唯一的缺点是您不完全知道将执行哪个Bash。另请参阅以下问答:
这里是如何在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)
检查此cmd使用的当前shell:
echo $SHELL
例如它可能会说/bin/bash
在--version
上运行$SHELL
:
/bin/bash --version
它可能会输出类似GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin16)
的内容
如果是版本4之前的版本,则必须升级。
检查您是否已经拥有版本4的bash shell。尝试运行:
bash --version
如果是这样,您只需要将默认外壳程序更改为该外壳程序。
您可以使用这些cmds来这样做:
sudo bash -c 'echo /usr/local/bin/bash >> /etc/shells'
sudo chsh -s /usr/local/bin/bash
首先将外壳添加到允许的外壳中。第二个实际上更改了您的默认外壳。
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
这将返回值“满足您”。
上面没有任何帮助,所以我打开了/ etc / shells并更改了该行-/bin/bash
至/usr/local/bin/bash
,然后重新加载source /etc/shells
,现在我可以享受bash v4的新可能性
[旧BASH版本不支持声明数组的declare -A
语法。我建议使用这两种形式之一在bash中声明数组,以使其与生产系统的较旧bash版本兼容:
arr=( '10' '20' '30' )
echo ${arr[@]}
或
arr[0]=10
arr[1]=20
arr[2]=30
echo ${arr[@]}
根据命令:
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命令中的用法字符串进行比较。似乎只是给定机器不支持。
尝试使用其他shebang。在我的Mac上:
$ which bash
/usr/local/bin/bash
因此,此脚本运行良好,生成了“ Hello World”:
#!/usr/local/bin/bash
declare -A assoc
assoc[hello]="Hello World"
echo ${assoc[hello]}