带有Variable键的bash关联键

时间:2017-05-18 21:50:25

标签: bash

我尝试创建一个数组,然后使用以下命令获取键的值:

declare -A email_addresses
mail_address=(["dev"]="dev.com" ["sandbox"]="sandbox.com")
env=$(#command to get env) # result is "sandbox"
echo ${email_address[$env]}

然而,它一直向我抛出这个错误:-bash: "hsandbox": syntax error: operand expected (error token is ""sandbox"")

我不知道如何克服这个问题。如果我执行echo $env,则会返回"sandbox"而不是""sandbox"",所以我不确定这似乎是什么问题。

1 个答案:

答案 0 :(得分:2)

修复你的“命令以获取env”不在其输出中发出文字引号。除非:

# strip leading and trailing quotes from env
env=${env%'"'}; env=${env#'"'}

echo "${email_address[$env]}"

Python-Audience-Friendly Explaour

以对知道Python的人有意义的方式来解释这一点(因为那是OP的大部分代表来自的地方):

shell中的

echo "$foo"行为类似于Python命令print str(foo),而不是Python命令print repr(foo)

考虑以下REPL会话:

>>> mail_address = { "dev": "dev.com", "sandbox": "sandbox.com" }
>>> env = getSomething()
>>> print str(env)
"dev"
>>> print mail_address[env]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: '"dev"'
>>> print repr(env)
'"dev"'

您遇到了完全相同的问题:您的词典包含dev作为其文字内容,但您的密钥的文字内容为"dev"

避免未来的混乱:明确地打印壳变量

如果你想以一种明确的方式在shell中打印变量的内容(在print repr(env)在Python中明确无误的同一方面),echo是错误的工具。请考虑以下其中一项:

$ declare -p env           ## caveat: doesn't work for all non-printable characters
declare -- env="\"dev\""
$ printf 'env=%q\n' "$env" ## caveat: doesn't work for non-string datatypes
env=\"dev\"

一个旁白:为什么你应该总是引用echo(或不使用它)的参数

虽然它看起来无害,但代码

echo $foo

实际上有令人惊讶的复杂行为。请考虑以下事项:

foo=$'\thello\tworld\t*\n\\text'

这是与以下Python等效的bash:

foo='\thello\tworld\t*\n\\text'

现在,让我们看看如果您实际使用echo将其打印到echo $foo会发生什么,如果您有IFS的默认值并且您的shell是bash:

  • 第一个标签完全消失
  • 其他标签由空格替换
  • 换行文字由空格
  • 取代
  • *将替换为当前目录中的文件列表。

也就是说,echo $foo的bash中的行为等同于以下Python:

import itertools, glob
foo='\thello\tworld\t*\n\\text'
print ' '.join(itertools.chain(*[ glob.glob(s) for s in foo.split() ]))

相比之下,请考虑:

echo "$foo"

在这种情况下,你会在bash中获得预期的行为。

为什么“在bash”?因为当文本中包含任何反斜杠文字时,POSIX standard for echo 未指定行为。 echo在这种情况下可以做任何事情,并且仍然符合POSIX标准,而BSD风格的实现将与XSI风格的实现不同。