2017-10-09 37 views
0

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

我有我的变量$输入里面确实有一个ERRMSG成员引用的JSON文件,但作为一个空字符串(请注意,我的命令行提示符为〜$):

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

检索在ERRMSG场这种情况下,适当地产生一个空字符串:

~$ err=$(jq ".errMsg" $input) 
~$ echo $err 
"" 

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

~$ if [ $err = "" ]; then echo EMPTY; else echo CONTENT; fi 
CONTENT 

由于$ err刚刚显示“”,我意识到EMPTY。检查其他方式:

~$ if [ $err != "" ]; then echo EMPTY; else echo CONTENT; fi 
EMPTY 

所以$ err显然不是“”,即使echo $ err yield“”? 这怎么可能?我在这里错过了什么bash功能?

无论如何,让我们尝试用一个非空的JSON(改变$输入内容后):

~$ 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' 

好,然后屏蔽这样的:

~$ if [ "$err" != "" ]; then echo EMPTY; else echo CONTENT; fi 
bash: syntax error near unexpected token `then' 

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

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

它也适用于非空ERRMSG成员。请,那里必须是一个简单而优雅的解决方案。

+0

'[$ err =“”]'不安全的bash代码;与'jq'无关。如果'err'为空,则运行'[=“”]',这是无效的语法。你需要'[“$ err”=“”]'。 –

+0

至于'''if [“$ err”!=“”];然后回显EMPTY;其他回声CONTENT; fi''' - 它真的,真的*不是*语法错误(尽管'!='意味着有逻辑错误)。看到它正确运行在https://ideone.com/CblHNK –

+0

...如果你可以提供[mcve]的代码形式,其他人可以复制和粘贴以重现该特定的错误(理想情况下,测试的复制器在ideone或另一个不偏不倚的第三方沙箱上工作),我很乐意看到它。 –

回答

1

让我们从顶部看这个,以便了解发生了什么。

~$ err=$(jq ".errMsg" $input) 
~$ echo $err 
"" 

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

~$ if [ $err = "" ]; then echo EMPTY; else echo CONTENT; fi 
CONTENT 

我excpected的EMPTY为$犯错只是显示 “”。

如前所述,$err不为空,它包含两个双引号。 另一方面,在Bash声明[ ... = "" ]中,""确实意味着一个空值。

Bash的声明[ $err = "" ]是有问题的,因为 这将导致语法错误如果$err值为空, 或者如果它包含空白(假设你没有定制IFS)。

写这个说法在双引号括$err正确的方法:

if [ "$err" = "" ]; then echo EMPTY; else echo CONTENT; fi 

这同样适用于你的第一个命令的$input变量,应该写成:

err=$(jq ".errMsg" "$input") 

如果您想检查对象中是否有空的​​值,请使用至少两个选项: 。选项1:检查值为""

if [ "$err" = '""' ]; then echo EMPTY; else echo CONTENT; fi 

选项2:使原始模式jq输出,所以它不包含字符串值的两边封闭双引号。

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

我推荐这后一个选项,以便err的值将是真正的值。封闭的双引号似乎只是为了您的目的。

+0

谢谢,那jq -r正是我们所需要的。简短,简洁的作品。不再需要sed。 – onouv

+0

@onouv如果这回答了您的问题,那么也许您可以将其标记为已接受。 – janos

1

你可以阅读你的整个结构成一个原生的bash关联数组如下:

declare -A data=() 
while IFS=$'\t' read -r key value; do 
    data[$key]=$value 
done < <(jq -r 'to_entries[] | [.key, .value] | @tsv' "$input") 

从那里,你有几种选择:你可以逐个检查项目...

[[ ${data[errMsg]} ]] || echo "ERROR: errMsg is not set!" 

。 ..或者你可以遍历所有这些:

for key in "${!data[@]}"; do 
    [[ ${data[$key]} ]] || echo "ERROR: ${key} is not set!" 
done