bash JSON with jq - 如何检查空 JSON 成员?

ono*_*ouv 6 bash json if-statement jq

我想根据错误消息 JSON 字段为空或非空来检测错误。我正在使用 jq 来分割成员,但在我的 bash“if”中评估它时遇到了很大的麻烦。

我的变量 $input 引用了一个 json 文件,该文件确实有一个 errMsg 成员,但作为一个空字符串(请注意,我的 CLI 提示符是 ~$):

~$ echo $(jq "." $input)
{ "projectCode": "145", "fullCode": "1", "errMsg": "" }
Run Code Online (Sandbox Code Playgroud)

在这种情况下检索 errMsg 字段会正确生成一个空字符串:

~$ err=$(jq ".errMsg" $input)
~$ echo $err
""
Run Code Online (Sandbox Code Playgroud)

问题:测试该变量似乎不可能:

~$ if [ $err = "" ]; then echo EMPTY; else echo CONTENT; fi 
CONTENT
Run Code Online (Sandbox Code Playgroud)

我期望 EMPTY 因为 $err 刚刚显示“”。检查其他方式:

~$ if [ $err != "" ]; then echo EMPTY; else echo CONTENT; fi
EMPTY 
Run Code Online (Sandbox Code Playgroud)

所以 $err 显然不是 "",即使 echo $err 产生 "" ?怎么可能 ?我在这里缺少什么 bash 功能?

无论如何,让我们尝试使用非空 json (更改 $input 内容后):

~$ echo $(jq "." $input)
{ "projectCode": "145", "fullCode": "1", "errMsg": "not empty" }
~$ echo $err
"not empty"

~$ if [ $err != "" ]; then echo EMPTY; else echo CONTENT; fi
bash: syntax error near unexpected token `then'
Run Code Online (Sandbox Code Playgroud)

好的,然后像这样屏蔽:

~$ if [ "$err" != "" ]; then echo EMPTY; else echo CONTENT; fi
bash: syntax error near unexpected token `then'
Run Code Online (Sandbox Code Playgroud)

我猜它在“not”之后找到了第二个标记并且不喜欢它。经过大量研究,我发现这个真正不可读的解决方案似乎有效:

~$ val=$(sed "s/^\(\"\)\(.*\)\1\$/\2/g" <<<"$err" | sed -e 's/\s.*$//')
~$ if [ "$val" = "" ]; then echo "NO ERROR"; else echo "ERROR"; fi
NO ERROR
Run Code Online (Sandbox Code Playgroud)

它也适用于非空 errMsg 成员。请一定有一个简单而优雅的解决方案。

Sto*_*ica 2

让我们从头开始回顾一下,以便您了解发生了什么。

~$ err=$(jq ".errMsg" $input)
~$ echo $err
""
Run Code Online (Sandbox Code Playgroud)

此输出表示err包含""(在 之前和之后也可能有一些空格"")。这与空字符串不同。它实际上是两个双引号字符。

~$ if [ $err = "" ]; then echo EMPTY; else echo CONTENT; fi 
CONTENT
Run Code Online (Sandbox Code Playgroud)

我期望 EMPTY 因为 $err 刚刚显示“”。

正如前面提到的,$err不是空的,它包含两个双引号。另一方面,在 Bash 语句中,[ ... = "" ]确实""意味着空值。

Bash 语句是有问题的,因为如果 的值为空,或者包含空格(假设您没有自定义) [ $err = "" ],则会导致语法错误。$errIFS

将此语句写$err在双引号中的正确方法是:

if [ "$err" = "" ]; then echo EMPTY; else echo CONTENT; fi
Run Code Online (Sandbox Code Playgroud)

第一个命令中的变量也是如此$input,它应该写成:

err=$(jq ".errMsg" "$input")
Run Code Online (Sandbox Code Playgroud)

如果你想检查.errMsg对象中的空值,你至少有两个选择。

选项 1:检查该值是否为""

if [ "$err" = '""' ]; then echo EMPTY; else echo CONTENT; fi
Run Code Online (Sandbox Code Playgroud)

选项 2:jq以原始模式进行输出,因此它不包含字符串值周围的双引号。

err=$(jq -r ".errMsg" "$input")
if [ "$err" = "" ]; then echo EMPTY; else echo CONTENT; fi
Run Code Online (Sandbox Code Playgroud)

我推荐后一个选项,这样 的值err才是真正的值。对于您的目的来说,封闭的双引号似乎只是噪音。