bash关联键与变量键

bash关联键与变量键,bash,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”:语法错误:应为操作数(错误标记为“sandbox”)

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

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”:语法错误:应为操作数(错误标记为“sandbox”)

我不知道如何度过这一关。如果我执行echo$env操作,它将返回
“sandbox”
而不是
“sandbox”
,因此我不确定问题出在哪里。

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

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

echo "${email_address[$env]}"

对观众友好的解释 要以对了解Python的人有意义的方式解释这一点(因为OP的大部分代表都来自Python):

echo“$foo”
在shell中的行为类似于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"'

旁白:为什么您应该总是引用
echo
(或不使用它)的参数 虽然看起来无害,但代码

echo $foo
实际上,它的行为异常复杂。考虑以下事项:

$ 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\"
foo=$'\thello\tworld\t*\n\\text'
这是与以下Python等效的bash:

foo='\thello\tworld\t*\n\\text'
import itertools, glob
foo='\thello\tworld\t*\n\\text'
print ' '.join(itertools.chain(*[ glob.glob(s) for s in foo.split() ]))
现在,让我们看看如果您实际使用
echo
echo$foo
打印它会发生什么,如果您有
IFS
的默认值,并且您的shell是bash:

  • 第一个选项卡将完全消失
  • 其他选项卡将替换为空格
  • 换行符文字替换为空格
  • *
    将替换为当前目录中的文件列表
也就是说,
echo$foo
在bash中的行为相当于以下Python:

foo='\thello\tworld\t*\n\\text'
import itertools, glob
foo='\thello\tworld\t*\n\\text'
print ' '.join(itertools.chain(*[ glob.glob(s) for s in foo.split() ]))
相比之下,请考虑:

echo "$foo"
在这种情况下,您将获得预期的行为。。。在狂欢节上

为什么“在bash中”?因为当文本中包含任何反斜杠文字时,不会指定行为
echo在这种情况下可以做任何事情,并且仍然是POSIX兼容的,BSD风格的实现的行为将不同于XSI风格的实现。

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

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

echo "${email_address[$env]}"

对观众友好的解释 要以对了解Python的人有意义的方式解释这一点(因为OP的大部分代表都来自Python):

echo“$foo”
在shell中的行为类似于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"'

旁白:为什么您应该总是引用
echo
(或不使用它)的参数 虽然看起来无害,但代码

echo $foo
实际上,它的行为异常复杂。考虑以下事项:

$ 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\"
foo=$'\thello\tworld\t*\n\\text'
这是与以下Python等效的bash:

foo='\thello\tworld\t*\n\\text'
import itertools, glob
foo='\thello\tworld\t*\n\\text'
print ' '.join(itertools.chain(*[ glob.glob(s) for s in foo.split() ]))
现在,让我们看看如果您实际使用
echo
echo$foo
打印它会发生什么,如果您有
IFS
的默认值,并且您的shell是bash:

  • 第一个选项卡将完全消失
  • 其他选项卡将替换为空格
  • 换行符文字替换为空格
  • *
    将替换为当前目录中的文件列表
也就是说,
echo$foo
在bash中的行为相当于以下Python:

foo='\thello\tworld\t*\n\\text'
import itertools, glob
foo='\thello\tworld\t*\n\\text'
print ' '.join(itertools.chain(*[ glob.glob(s) for s in foo.split() ]))
相比之下,请考虑:

echo "$foo"
在这种情况下,您将获得预期的行为。。。在狂欢节上


为什么“在bash中”?因为当文本中包含任何反斜杠文字时,不会指定行为
echo
在这种情况下可以做任何事情,并且仍然是POSIX兼容的,BSD风格的实现的行为将不同于XSI风格的实现。

如果
echo“$env”
在输出中完全包含引号,这意味着您的字符串数据中有文字引号。这些都是不可取的——在
mail\u address=([“sandbox”]=“sandbox.com”)
中,所有的引号都是语法的,而不是文字的。例如,如果您的“获取环境的命令”使用的是
jq
,请使用
-r
选项——用于原始输出——以避免引号文字。如果
echo“$env”
在输出中包含引号,这意味着您的字符串数据中有文字引号。这些是不可取的——在
mail_address=([“sandbox”]=“sandbox.com”)
中,所有的引号都是语法性的,而不是文字性的。例如,如果您的“获取环境的命令”使用的是
jq
,对于原始输出,使用
-r
选项以避免引用文字。您关于对
jq
使用
-r
的评论实际上解决了这个问题。呵呵。问题没有具体说明您使用的是
jq
,因此这在很大程度上是一种猜测,与文本支持的内容相反。:)是的,我的错。这个命令很长,而且似乎不相关。我完全忘记了我在结尾的jq部分,顺便说一句,我在一篇旁白中修改了shell中
echo$foo
的行为,它倾向于。。。令人惊讶。你关于将
-r
用于
jq
的评论实际上解决了这个问题。呵呵。问题没有具体说明您使用的是
jq
,因此这在很大程度上是一种猜测,与文本支持的内容相反。:)是的,我的错。这个命令很长,而且似乎不相关。我完全忘记了我在结尾的jq部分,顺便说一句,我在一篇旁白中修改了shell中
echo$foo
的行为,它倾向于。。。令人惊讶的