【问题标题】:bash script - unable to set variable with double quotes in valuebash脚本 - 无法在值中设置带有双引号的变量
【发布时间】:2017-04-22 22:41:53
【问题描述】:

需要帮助修复此 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" 用双引号括起来。

【问题讨论】:

  • export 在 shell 脚本中具有精确的含义,我没有看到任何证据表明该脚本中的任何变量正在被导出。
  • @noober,顺便说一句,运行mongo 比运行_mongo=$(which mongo) 然后调用"$_mongo" 更有效。后者生成一个子shell,然后调用一个外部进程来进行查找——这些步骤中的任何一个都单独比仅仅在shell本身内部进行PATH查找更昂贵。
  • @CharlesDuffy- 注意到了。会让这更简单。

标签: bash shell unix escaping quoting


【解决方案1】:

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

_account=foo
_account="foo"

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

_account='"foo"'

【讨论】:

  • 不只是 bash,还有基线 POSIX sh(因此,该系列中的所有 shell)。
  • 感谢大家的帮助。在双引号周围添加单引号有效。
  • 谢谢@CharlesDuffy - 我已经修改了我的答案以包括这个。
  • 几乎没有理由在变量_account_profile 的值中包含引号; exp 的值需要引号。
  • 引号将包含在变量中,因此当变量在exp 中展开时,附加到_account 的引号也将包含在内。
【解决方案2】:

由于您在此处所做的部分工作是形成 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}

【讨论】:

  • 也不错。绝对使这更加强大。谢谢。
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

    我需要引用变量中已经存在的内容并将其粘贴在变量中。扩展Robert Seaman's answer,我发现这很有效:

    VAR='"'$1'"'
    

    (单引号、双引号、单引号、
    变量、
    单引号、双引号、单引号)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-01-22
      • 1970-01-01
      • 2011-01-28
      • 2023-01-08
      • 2019-04-19
      • 1970-01-01
      相关资源
      最近更新 更多