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 成员。请一定有一个简单而优雅的解决方案。
让我们从头开始回顾一下,以便您了解发生了什么。
Run Code Online (Sandbox Code Playgroud)~$ err=$(jq ".errMsg" $input) ~$ echo $err ""
此输出表示err
包含""
(在 之前和之后也可能有一些空格""
)。这与空字符串不同。它实际上是两个双引号字符。
Run Code Online (Sandbox Code Playgroud)~$ if [ $err = "" ]; then echo EMPTY; else echo CONTENT; fi CONTENT
我期望 EMPTY 因为 $err 刚刚显示“”。
正如前面提到的,$err
不是空的,它包含两个双引号。另一方面,在 Bash 语句中,[ ... = "" ]
确实""
意味着空值。
Bash 语句是有问题的,因为如果 的值为空,或者包含空格(假设您没有自定义) [ $err = "" ]
,则会导致语法错误。$err
IFS
将此语句写$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
才是真正的值。对于您的目的来说,封闭的双引号似乎只是噪音。