验证 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 12:46:08  来源:igfitidea点击:

verify that a json field exists with jq and bash?

jsonbashjq

提问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_pathis now split into folderand file. The script was reading the file_path, now the foldermay 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现在拆分为folderfile。脚本正在读取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/flor null/flif 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 jqfilter:

我会在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 ifaccepts 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 is 0, false otherwise). The [you attempted to use is just a command (an alias for test, see man test) and not special in any way.
  • Shell 变量在使用时几乎总是被引用(即,"$MESSAGE"而不是$MESSAGE)。如果您的 JSON 中的一个字符串包含 shell 元字符(例如*)而您忘记这样做,您将遇到有趣的问题;该字符串将受到 shell 扩展(并且*将扩展为当前工作目录中的文件列表)。
  • shellif接受一个命令作为条件,并根据该命令的退出状态决定分支到哪里(如果退出状态为0,则为真,否则为假)。在[你试图使用只是一个命令(一个别名test,见man test),并以任何方式不特别。

So, the goal is to construct a command that exits with 0if the JSON object has a folderproperty, non-zero otherwise. jqhas a -eoption that makes it return 0if the last output value was not falseor nulland non-zero otherwise, so we can write

因此,目标是构建一个命令,0如果 JSON 对象具有folder属性,则该命令退出,否则为非零。jq有一个-e选项,0如果最后一个输出值不是falsenull非零则返回,否则我们可以写

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/nullbit redirects the output from jqto /dev/null(where it is ignored) so that we don't see it on the console.

> /dev/null位将输出重定向jq/dev/null(忽略它的地方),以便我们在控制台上看不到它。