bash script - невозможно установить переменную с двойными кавычками в значении
Нужна помощь в исправлении этого скрипта bash, чтобы установить переменную со значением, включающим двойные кавычки. Почему-то я неправильно определяю это как мои ценности foo
а также bar
при необходимости не заключаются в двойные кавычки.
Мой сценарий до сих пор:
#!/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"
быть заключенным в двойные кавычки.
4 ответа
В bash (и других оболочках POSIX) следующие 2 состояния эквивалентны:
_account=foo
_account="foo"
Что вы хотите сделать, это сохранить цитаты, поэтому вы можете сделать следующее:
_account='"foo"'
Поскольку часть того, что вы делаете здесь, формирует 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}
с именами ключей, выведенными из имен переменных.
Когда вам нужно использовать двойные кавычки внутри строки в двойных кавычках, экранируйте их обратной косой чертой:
$ foo="acount:\"foo\"" sh -c 'echo $foo'
acount:"foo"
Мне нужно было заключить что-то уже в переменную и вставить это в переменную. Расширяя ответ Роберта Симана , я обнаружил, что это сработало:
VAR='"'$1'"'
(одинарная кавычка, двойная кавычка, одинарная кавычка,
переменная,
одинарная кавычка, двойная кавычка, одинарная кавычка)