Вопрос или проблема
$ n="foo"; echo "{}" | jq --arg n "$n" '. += { "$n": $n }'
{
"$n": "foo"
}
Моё понимание https://jqlang.github.io/jq/manual/#types-and-values предполагает, что это должно работать, но явно это не так. В чём дело?
Вы можете добиться этого, обернув $n
в скобки, чтобы сказать jq оценить выражение:
n="foo"; echo "{}" | jq --arg n "$n" '. += { ($n): $n }'
Или, вероятно, более подходящим для этой задачи будет jo(1):
$ jo "$n"="$n"
{"foo":"foo"}
Я не уверен, ошибаются ли в документации или моё понимание недостаточно высоким, но, похоже, там говорится, что ваш пример должен работать:
Выражения ключей отличные от постоянных литералов, идентификаторов или ссылок на переменные должны быть в скобках, например, {(“a”+”b”):59}.
И кто-то мог бы предположить, что это относится к родной переменной jq, а не к одной, инъектированной оболочкой, поскольку они немного различаются, но, увы, обе должны быть обернуты в скобки:
$ echo '{}' | jq 'def myvar: "foo"; {myvar: myvar}'
{
"myvar": "foo"
}
$ echo '{}' | jq 'def myvar: "foo"; {(myvar): myvar}'
{
"foo": "foo"
}
Вы можете использовать:
$ n=foo
$ jq -cn --arg n "$n" '{$n:$n}'
{"foo":"foo"}
То есть использовать переменную $n
в качестве ключа, а не строку "$n"
. jq -n
аналогично echo null | jq
.
$ jq -cn --arg n "$n" '.[$n]=$n'
{"foo":"foo"}
При этом не используется конструктор объекта {...}
, а просто присваивается значение для данного ключа.
$ jq -cn --arg n "$n" '{"key\($n)":$n}'
{"keyfoo":"foo"}
Показывая, как разыменовать переменную jq
внутри строкового литерала (в \(expr)
expr
может быть любым выражением jq
, не только переменной).
$ jq -cn --arg n "$n" '{("key"+$n):$n}'
{"keyfoo":"foo"}
В конструкторе объекта, когда ключи должны быть результатом выражения jq
, они должны находиться внутри (...)
.
Ответ или решение
Для создания объекта с использованием переменной в качестве имени свойства в jq
, необходимо правильно использовать синтаксис, позволяющий указать ключи объектов с переменными. Ваш первоначальный пример не сработал, потому что вы использовали строку "$n"
вместо самой переменной n
. Для того чтобы правильно указать переменную в качестве ключа объекта, нужно обернуть её в круглые скобки.
Вот несколько способов сделать это:
-
Использование скобок для переменной:
Используйте следующий код, чтобы добавить переменную в качестве ключа:
n="foo" echo "{}" | jq --arg n "$n" '. += { ($n): $n }'
Выходом будет:
{ "foo": "foo" }
Заметьте, что вы используете
($n)
внутри фигурных скобок, что позволяетjq
понять, что это переменная. -
Использование
jq -n
:Для создания объекта с нуля, можно использовать ключ
-n
, который позволяет избежать необходимости начинать с пустого JSON:n="foo" jq -cn --arg n "$n" '{$n: $n}'
Это также даст вам:
{ "foo": "foo" }
-
Использование динамических ключей:
Вы можете использовать динамичные выражения для построения ключей. Например, если хотите создать ключ с префиксом, сделайте так:
jq -cn --arg n "$n" '{("key" + $n): $n}'
Результат будет:
{ "keyfoo": "foo" }
-
Доступ к значению по ключу:
Если необходимо создать или модифицировать объект, используя переменную в качестве ключа, используйте:
jq -cn --arg n "$n" '.[$n] = $n'
Это также создаст объект с результатом:
{ "foo": "foo" }
Все эти методы демонстрируют, как правильно работать с переменными в jq
для создания объектов с динамическими названиями свойств. Настоятельно рекомендуется всегда использовать круглые скобки при работе с изменяемыми ключами в объектах jq
, чтобы избежать неожиданного поведения.