验证 jq 和 bash 是否存在 json 字段?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29563145/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
verify that a json field exists with jq and bash?
提问by sop
I have a script that uses jq for parsing a json string MESSAGE
(that is read from another application). Meanwhile the json has changed and a field is split in 2 fields: file_path
is now split into folder
and file
. The script was reading the file_path
, now the folder
may not be present, so for creating the path of the file I have to verify if the field is there. I have search for a while on the internet, and manage to do:
我有一个使用 jq 解析 json 字符串MESSAGE
(从另一个应用程序读取)的脚本。同时 json 发生了变化,一个字段被拆分为 2 个字段:file_path
现在拆分为folder
和file
。脚本正在读取file_path
,现在folder
可能不存在,因此为了创建文件的路径,我必须验证该字段是否存在。我在互联网上搜索了一段时间,并设法做到了:
echo $(echo $MESSAGE | jq .folder -r)$'/'$(echo $MESSAGE | jq .file -r)
if [ $MESSAGE | jq 'has(".folder")' -r ]
then
echo $(echo $MESSAGE | jq .folder -r)$'/'$(echo $MESSAGE | jq .file -r)
else
echo $(echo $MESSAGE | jq .file -r)
fi
where MESSAGE='{"folder":"FLDR","file":"fl"}'
or MESSAGE='{"file":"fl"}'
哪里MESSAGE='{"folder":"FLDR","file":"fl"}'
或MESSAGE='{"file":"fl"}'
The first line is printing FLDR/fl
or null/fl
if the folder field is not present. So I have thought to create an if that is verifying if the folder field is present or not, but it seems that I am doing it wrong and cannot figure out what is wrong. The output is
第一行正在打印FLDR/fl
或者null/fl
文件夹字段不存在。所以我想创建一个 if 来验证文件夹字段是否存在,但似乎我做错了,无法弄清楚出了什么问题。输出是
bash: [: missing `]'
jq: ]: No such file or directory
null/fl
回答by Wintermute
I'd do the whole thing in a jq
filter:
我会在jq
过滤器中完成整个事情:
echo "$MESSAGE" | jq -r '[ .folder, .file ] | join("/")'
In the event that you want to do it with bash (or to learn how to do this sort of thing in bash), two points:
如果你想用 bash 来做(或学习如何用 bash 做这种事情),两点:
- Shell variables should almost always be quoted when they are used (i.e.,
"$MESSAGE"
instead of$MESSAGE
). You will run into funny problems if one of the strings in your JSON ever contains a shell metacharacter (such as*
) and you forgot to do that; the string will be subject to shell expansion (and that*
will be expanded into a list of files in the current working directory). - A shell
if
accepts as condition a command, and the decision where to branch is made depending on the exit status of that command (true if the exit status is0
, false otherwise). The[
you attempted to use is just a command (an alias fortest
, seeman test
) and not special in any way.
- Shell 变量在使用时几乎总是被引用(即,
"$MESSAGE"
而不是$MESSAGE
)。如果您的 JSON 中的一个字符串包含 shell 元字符(例如*
)而您忘记这样做,您将遇到有趣的问题;该字符串将受到 shell 扩展(并且*
将扩展为当前工作目录中的文件列表)。 - shell
if
接受一个命令作为条件,并根据该命令的退出状态决定分支到哪里(如果退出状态为0
,则为真,否则为假)。在[
你试图使用只是一个命令(一个别名test
,见man test
),并以任何方式不特别。
So, the goal is to construct a command that exits with 0
if the JSON object has a folder
property, non-zero otherwise. jq
has a -e
option that makes it return 0
if the last output value was not false
or null
and non-zero otherwise, so we can write
因此,目标是构建一个命令,0
如果 JSON 对象具有folder
属性,则该命令退出,否则为非零。jq
有一个-e
选项,0
如果最后一个输出值不是false
或null
非零则返回,否则我们可以写
if echo "$MESSAGE" | jq -e 'has("folder")' > /dev/null; then
echo "$MESSAGE" | jq -r '.folder + "/" + .file'
else
echo "$MESSAGE" | jq -r .file
fi
The > /dev/null
bit redirects the output from jq
to /dev/null
(where it is ignored) so that we don't see it on the console.
该> /dev/null
位将输出重定向jq
到/dev/null
(忽略它的地方),以便我们在控制台上看不到它。