Сжать объявление heredoc до одной строки в bash?
У меня есть это, которое работает, чтобы объявить строку JSON в сценарии bash:
local my_var="foobar"
local json=`cat <<EOF
{"quicklock":"${my_var}"}
EOF`
Вышеупомянутый heredoc работает, но я не могу отформатировать его каким-либо другим способом, он буквально должен выглядеть точно так же, как это смеется.
Есть ли способ заставить команду находиться в одной строке, примерно так:
local json=`cat <<EOF{"quicklock":"${my_var}"}EOF`
это было бы намного приятнее, но, похоже, это не так, очевидно просто потому, что EOF работает не так, я думаю, смеется.
Я ищу краткий способ объявить JSON в файле, который:
- Не требует тонны спасательных символов.
- Это позволяет для динамической интерполяции переменных.
Примечание: фактический JSON, который я хочу использовать, имеет несколько динамических переменных со многими парами ключ / значение. Пожалуйста, экстраполируйте.
6 ответов
Почему бы не использовать JQ? Он очень хорошо справляется с интерполяцией строк и определяет вашу структуру.
$ echo '{}' >> foo.json
$ local myvar="assigned-var"
$ jq --arg ql $myvar '.quicklock=$ql' foo.json
текст, который выходит на другом конце этого вызова к JQ может быть cat
в файл или что вы хотите сделать. текст будет выглядеть примерно так:
{"quicklock"="assigned-var"}
Я не JSON, не очень понимаю "правильно сформированные" аргументы в обсуждении выше, но вы можете использовать "здесь-строку", а не "здесь-документ", например так:
my_var="foobar"
json=`cat <<<{\"quicklock\":\"${my_var}\"}`
Надеюсь, это поможет.
Вы можете сделать это с помощью printf:
local json="$(printf '{"quicklock":"%s"}' "$my_var")"
(Не берите в голову, что подсветка синтаксиса SO выглядит здесь странно. Подстановка команд оболочки Posix позволяет вкладывать один уровень кавычек.)
Примечание (благодаря комментарию Чарльза Даффи по этому вопросу): я предполагаю $my_var
не контролируется пользовательским вводом. Если это так, вам нужно быть осторожным, чтобы убедиться, что это допустимо для строки JSON. Я настоятельно рекомендую запретить символы не ASCII, двойные кавычки и обратную косую черту. Если у вас есть jq
доступно, вы можете использовать его, как Чарльз отметил в комментариях, чтобы убедиться, что у вас есть правильно сформированный вывод.
Вы можете определить свою собственную вспомогательную функцию для решения ситуации с отсутствующим синтаксисом bash:
function begin() { eval echo $(sed "${BASH_LINENO[0]}"'!d;s/.*begin \(.*\) end.*/\1/;s/"/\\\"/g' "${BASH_SOURCE[0]}"); }
Тогда вы можете использовать его следующим образом.
my_var="foobar"
json=$(begin { "quicklock" : "${my_var}" } end)
echo "$json"
Этот фрагмент отображает желаемый результат:
{ "quicklock" : "foobar" }
Это просто доказательство концепции. Вы можете определить свой синтаксис любым способом (например, конец ввода пользовательской строкой EOF, корректно экранировать недопустимые символы). Например, поскольку Bash позволяет идентификаторам функций использовать символы, отличные от буквенно-цифровых символов, возможно определить такой синтаксис:
json=$(/ { "quicklock" : "${my_var}" } /)
Более того, если вы ослабите первый критерий (escape-символы), обычное присваивание хорошо решит эту проблему:
json="{ \"quicklock\" : \"${my_var}\" }"
Поскольку никакие escape-символы не являются сильным требованием, вот решение на основе here-doc:
#!/bin/bash
my_var='foobar'
read -r -d '' json << EOF
{
"quicklock": "$my_var"
}
EOF
echo "$json"
Это даст вам тот же результат, что и первое решение, которое я упомянул.
Просто будьте осторожны, если вы поставите первым EOF
внутри двойных кавычек:
read -r -d '' json << "EOF"
$my_var
будет рассматриваться не как переменная, а как простой текст, поэтому вы получите такой вывод:
{
"quicklock": "$my_var"
}
Как насчет использования естественной конкатенации строк в оболочке? Если вы объедините ${mybar}
вместо того, чтобы интерполировать его, вы можете избежать побегов и получить все в одной строке:
my_var1="foobar"
my_var2="quux"
json='{"quicklock":"'${my_var1}'","slowlock":"'$my_var2'"}'
Тем не менее, это довольно грубая схема, и, как уже отмечали другие, у вас будут проблемы, если переменные, скажем, содержат символы кавычек.