jq & bash: сделать массив JSON из переменной
Я использую jq для формирования JSON в bash из значений переменных.
Получил, как сделать простые переменные
$ VAR="one two three"
$ jq -n "{var:\"$VAR\"}"
{
"var": "one two three"
}
Но он не может создавать массивы. у меня есть
$ echo $ARR
one
two
three
и хотите получить что-то вроде
{
"arr": ["one", "two", "three"]
}
Мне только удается получить искаженный вывод, как
$ jq -n "{arr: [\"$ARR\"]}"
{
"arr": [
"one\ntwo\nthree"
]
}
Как правильно сформировать массив JSON? Может ли jq
это сделать?
EDIT: вопрос был задан, когда был только jq 1.3. Теперь, в jq 1.4, можно сделать то, о чем я просил, например, @JeffMercado и @peak, предложили им возвышение. Однако не отменит принятие ответа @jbr.
Ответы
Ответ 1
jq
делает именно то, что вы говорите ему. jq
- не программа для генерации JSON, а инструмент для его запроса. То, что вы делаете с коммутатором -n
просто использует его как красивый принтер. Поэтому, если вы хотите, чтобы он печатал объект с массивом, содержащим "один", "два", "три", вы должны его сгенерировать.
VAR="one two three"
VAR=$(echo $VAR | sed -e 's/\(\w*\)/,"\1"/g' | cut -d , -f 2-)
echo "{var: [$VAR]}"
Обновить
Как упоминает Брайан и другие ниже, действительно возможно генерировать JSON с jq, а с версии 1.4 можно даже делать то, что OP задает напрямую, см., Например, ответ Джеффа.
Ответ 2
В jq 1.3 и выше вы можете использовать --arg VARIABLE VALUE
командной строки --arg VARIABLE VALUE
:
jq -n --arg v "$VAR" '{"foo": $v}'
Т.е., --arg
устанавливает переменную в заданное значение, поэтому вы можете использовать $varname
в вашей jq-программе, и теперь вам не нужно использовать интерполяцию переменных оболочки в вашу jq-программу.
EDIT: из jq 1.5 и выше вы можете использовать --arg json для передачи в массиве напрямую, например
jq -n --argjson v '[1,2,3]' '{"foo": $v}'
Ответ 3
Если у вас есть переменная загружена, вы должны использовать split
фильтр, чтобы разделить эту строку в массив.
$ jq -n --arg inarr "${ARR}" '{ arr: $inarr | split("\n") }'
Ответ 4
В оригинальной публикации в этой теме упоминается VAR = "один два три". Для такой переменной очень простое решение в jq 1.4 выглядит следующим образом:
$ jq -n -c -M --arg s "$VAR" '{var: ($s|split(" "))}'
{"var":["one","two","three"]}
(Это предполагает оболочку Linux или Mac или аналогичную, и работает с jq 1.4.)
Если символ разделителя является символом новой строки, тогда рассмотрим этот машинописный текст:
$ s=$(printf "a\nb\nc\n")
$ jq -n -c -M --arg var "$s" '{"var": ($var|split("\n"))}'
{"var":["a","b","c"]}
Обратите внимание, что строка JSON для символа новой строки - "\n"
(не "\\n"
).
Третий случай представляет интерес, когда VAR является массивом bash. В этом случае может быть приемлемым передать элементы, используя "$ {VAR [@]}", но в целом следует помнить, что значение "--arg name name" предназначено только для передачи в строках.
В jq> 1.4 экспортируемые переменные оболочки могут быть переданы с использованием объекта env, как описано на странице справочника онлайн jq.
Ответ 5
Сначала вы должны использовать -R
для чтения необработанных строк, а затем вам нужно сбросить все значения с помощью -s
:
$ echo -e "one\ntwo\nthree" | jq -R . | jq -s '{"arr": .}'
{
"arr": [
"one",
"two",
"three"
]
}
Ответ 6
Вы можете использовать этот синтаксис:
jq --arg keyName "MyVal" '.[]."\($keyName)"[] ./JSONFile.js
для входных данных, таких как
[{"MyVal":"Value1","MyVal":Value2,"NotMyVal":"Value3"}];
для получения анализируемых данных из JSON с переменными.
В этом примере будет напечатан:
"Value1"
"Value2"