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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43565409/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 16:03:14  来源:igfitidea点击:

bash script - unable to set variable with double quotes in value

bashshellunixescapingquoting

提问by noober

Need help in fixing this bash script to set a variable with a value including double quotes. Somehow I am defining this incorrectly as my values fooand barare not enclosed in double quotes as needed.

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

My script thus far:

到目前为止我的脚本:

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

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

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

set +x

Output shows:

输出显示:

+ 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

What i need is account:"foo", profile:"bar"to be enclosed in double quotes.

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

回答by Robert Seaman

In bash (and other POSIX shells), the following 2 states are equivalent:

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

_account=foo
_account="foo"

What you want to do is to preserve the quotations, therefore you can do the following:

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

_account='"foo"'

回答by Charles Duffy

Since part of what you're doing here is forming JSON, consider using jq-- which will guaranteethat it's well-formed, no matter what the values are.

由于您在这里所做的部分工作是形成 JSON,请考虑使用jq-- 这将保证它的格式正确,无论值是什么。

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

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"

This makes jqresponsible for adding literal quotes where appropriate, and will avoid attempted injection attacks (for instance, via a version passed in $1containing something like 1, "other_argument": "malicious_value"), by replacing any literal "in a string with \"; a literal newline with \n, etc -- or, with the | tonumberconversion, failing outright with any non-numeric value.

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



Note that some of the syntax above requires jq 1.5 -- if you have 1.4 or prior, you'll want to write {account: $account, profile: $profile}instead of being able to write {$account, $profile}with the key names inferred from the variable names.

请注意,上面的某些语法需要 jq 1.5——如果您有 1.4 或更低版本,您将需要编写{account: $account, profile: $profile}而不是能够{$account, $profile}使用从变量名称推断出的键名称进行编写。

回答by PSkocik

When you need to use double quotes inside a double quoted string, escape them with backslashes:

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

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