bash脚本 - 无法在值中设置带双引号的变量

时间:2017-04-22 22:41:54

标签: bash shell unix escaping quoting

需要帮助修复此bash脚本以设置包含双引号值的变量。不知何故,我错误地定义了这个,因为我的值foobar没有根据需要用双引号括起来。

到目前为止我的脚本:

#!/usr/local/bin/bash
set -e
set -x

host='127.0.0.1'
db='mydev'
_account="foo"
_profile="bar"
_version=$1
_mongo=$(which mongo);

exp="db.profile_versions_20170420.find({account:${_account}, profile:${_profile}, version:${_version}}).pretty();";
${_mongo} ${host}/${db} --eval "$exp"

set +x

输出显示:

+ host=127.0.0.1
+ db=mydev
+ _account=foo
+ _profile=bar
+ _version=201704112004
++ which mongo
+ _mongo=/usr/local/bin/mongo
+ exp='db.profile_versions_20170420.find({account:foo, profile:bar, version:201704112004}).pretty();'
+ /usr/local/bin/mongo 127.0.0.1/mydev --eval 'db.profile_versions_20170420.find({account:foo, profile:bar, version:201704112004}).pretty();'
MongoDB shell version: 3.2.4
connecting to: 127.0.0.1/mydev
2017-04-22T15:32:55.012-0700 E QUERY    [thread1] ReferenceError: foo is not defined :
@(shell eval):1:36

我需要的是account:"foo"profile:"bar"用双引号括起来。

3 个答案:

答案 0 :(得分:6)

由于您在此处所做的部分工作是形成JSON,请考虑使用jq - 保证,无论值是什么,它都是格式良好的。

host='127.0.0.1'
db='mydev'
_account="foo"
_profile="bar"
_version=$1

json=$(jq -n --arg account "$_account" --arg profile "$_profile" --arg version "$_version" \
  '{$account, $profile, version: $version | tonumber}')

exp="db.profile_versions_20170420.find($json).pretty();"
mongo "${host}/${db}" --eval "$exp"

这使得jq负责在适当的位置添加文字引号,并且会避免尝试注入攻击(例如,通过$1中传递的包含类似1, "other_argument": "malicious_value"的内容的版本),通过替换带有"的字符串中的任何文字\";带有\n等的文字换行符,或者| tonumber转换后,与任何非数字值完全失败。

请注意,上面的一些语法需要jq 1.5 - 如果您有1.4或之前的版本,则需要编写{account: $account, profile: $profile}而不是能够使用从中推断的密钥名称来编写{$account, $profile}变量名。

答案 1 :(得分:5)

在bash(和其他POSIX shell)中,以下两种状态是等效的:

_account=foo
_account="foo"

您要做的是保留报价,因此您可以执行以下操作:

_account='"foo"'

答案 2 :(得分:1)

当您需要在双引号字符串中使用双引号时,请使用反斜杠转义它们:

$ foo="acount:\"foo\"" sh -c 'echo $foo'
  acount:"foo"