我正在尽我最大的努力弄清楚如何告诉我的一个脚本的用户他们传递了一个jq 1.5
无效的查询。
下面是一个简单的示例 JSON:
{ "foo": { "bar":"baz" } }
我希望能够在用户提供.foo.bax
等查询时向用户显示错误消息,但当他们提供正确的查询(如.foo.bar
)时,baz
返回值。
我无法(或不知道如何)读取jq
的返回值,因为我需要在子外壳中运行jq
,即:
value="$(echo -e "${json}" | jq -r "${query}")"
当我给它一个无效的查询时,jq
总是返回一个null
字符串。 但我无法将其与可能包含在 JSON 文件中的null
值区分开来,作为"property": "null"
.
看起来jq
有各种功能,我可以使用它们,但我无法弄清楚我将如何使用它们。
那么有没有办法让jq
来验证查询,我可以分辨出null
和"null"
之间的区别?
更新
当我问这个问题时,我希望找到的是一个大致等同于"$(jq.validate("${query}") && echo "valid")"
的语法,假设jq
有一个validate()
方法。
您可以在jq
中使用标志将jq
的退出代码传播到 shell,您可以在命令中使用该代码来查看它是否成功。
官方的jq文档为此提供了正确的选择,
-e/--退出状态:
如果最后一个输出值既不是
false
也不是null
,1
最后一个输出值是false
或null
,则jq
的退出状态设置为0
,如果没有产生任何有效结果,则4
。通常,如果存在任何使用问题或系统错误,3
如果存在jq
程序编译错误,或者如果jq
程序运行,0
,jq
会退出2
。
您可以看到它的用法如下:-
jsonStr='{"foo": 42, "bar": "less interesting data"}'
jq -er '.foo' <<<"$jsonStr"
42
echo $?
0
现在对于失败案例,
jq -er '.foo1' <<<"$jsonStr"
null
echo $?
1
请记住,如果您不设置-e
标志,则上述情况是不可能的,因为请参阅上述子句的最后一行
或
0
jq
程序是否运行
因此,除非您设置-e
标志,否则错误代码不会传播到 shell。
(或者)使用 if 子句的更有意义的 shell 构造是执行以下操作,
jsonStr='{"foo": 42, "bar": "less interesting data"}'
if jq -er '.foo' <<<"$jsonStr" > /dev/null; then
printf "string contained foon"
fi
对于失败的情况,
if jq -er '.foo1' <<<"$jsonStr" > /dev/null; then
printf "string contained foon"
else
printf "string does not contain foon"
fi
如果您仔细观察,将转到故障情况的else
部分,这是您的意图。如果未设置-e
标志,则仍会0
失败案例退出代码,并且会满足真实条件。
>/dev/null
部分只是为了抑制命令jq
生成到空流stdout
。
另请注意,-e
仅从 jq-1.4 开始引入。
请注意,如果使用-e
选项,则 JSON 值false
也会触发错误条件。
如果目标是能够区分 JSON 值null
和 JSON 字符串"null"
, 那么请注意,这也可以通过不使用"-r"选项来完成。
如果你真的需要结果,好像是由jq -r
生成的,那么考虑首先使用jq "$query"
和 然后使用 -r 选项再次调用 jq。
我(作为一个jq菜鸟)会像这样验证它:
query()(
local q=$1
local json='{"foo":"bar"}'
local value=$(jq -r "if($q) then $q else empty end" <<<"$json" 2>/dev/null)
if ! test -n "$value"; then
echo "You've done it all wrong"
return 1
fi >&2
echo "$value"
)
在行动中:
$ query foo
You've done it all wrong
$ query .foo
bar
$ echo $?
0
$ query .foo1
You've done it all wrong
$ echo $?
1