1

我正在尝试用“BAR”替换“${FOO}”(请注意:“${FOO}”不是 shell 变量 - 这是它在 json 中的显示方式,我无法控制 json)

这有效:

echo '{ "name": "${FOO}" }' | \
    jq '.|(select (.name == "${FOO}") | .name) |= "BAR"'

{
  "name": "BAR"
}

但是,如果我想以编程方式分配匹配值(MYVAR=FOO在这种情况下),我无法让它工作,例如

echo '{ "name": "${FOO}" }' | \
    jq --arg MYVAR FOO '.|(select (.name == "${$MYVAR}") | .name) |= "BAR"'
{
  "name": "${FOO}"
}

我的直觉是匹配字符串周围的引号是问题所在,因为这也有效:

echo '{ "name": "FOO" }' | \
    jq --arg MYVAR FOO '.|(select (.name == $MYVAR) | .name) |= "BAR"'
{
    "name": "BAR"
}
4

1 回答 1

0

首先,您永远不需要首字母.|,因为.这里只是“身份”过滤器。

其次,区分 shell 变量和 jq $-variables 是很重要的。除非你明确地将两者联系在一起,否则他们将拥有完全独立的生活。如您所见, using--arg MYVAR FOO将 jq 变量$MYVAR设置为 JSON 字符串"FOO";要引用此变量,您只需$MYVAR在 jq 程序中编写。

也可以使用以下方法初始化 jq 变量:

--arg MYVAR "${MYVAR}"

这会将 jq 变量设置为 shell 变量的(字符串)值。

第三,jq "$-variables" 的名称是高度约束的:除了开头的"$",它们必须匹配正则表达式:[a-zA-Z_][a-zA-Z_0-9]*

因此,如果您的真正目标是用“BAR”更改 JSON 字符串“${FOO}”的出现,其中 FOO 将以编程方式指定,您将不得不采用不同的策略。这会起作用:

echo '{ "name": "${FOO}" }' |
  jq -c --arg MYVAR FOO --arg MYVALUE BAR '
    if .name == "${\($MYVAR)}" then .name = $MYVALUE else . end'

这会产生: {"name":"BAR"}

另请参阅jq Cookbook中的“使用 jq 作为模板引擎”部分。

于 2018-06-12T05:30:53.137 回答