簡體   English   中英

bash JSON與jq-如何檢查空的JSON成員?

[英]bash JSON with jq - how to check for empty JSON members?

我想根據錯誤消息JSON字段為空或非空來檢測錯誤。 我正在使用jq切出該成員,但是在我的bash“ if”中評估它有很大的麻煩。

我有一個變量$ input引用的json文件,該文件確實具有errMsg成員,但為空字符串(請注意,我的CLI提示符是〜$):

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

我期望EMPTY為空,因為$ err僅顯示“”。 檢查其他方法:

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

因此,即使echo $ err產生“”,$ 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'

好吧,然后像這樣屏蔽:

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

我猜它會在“ not”之后找到第二個令牌,並且不喜歡它。 經過大量研究,我發現這個似乎難以理解的解決方案似乎有效:

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

它也適用於非空errMsg成員。 請,必須有一個簡單而優雅的解決方案。

讓我們從頂部開始進行研究,以便您了解正在發生的事情。

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

此輸出表明err包含"" (在""之前和之后也可能有一些空格)。 這與空字符串不同。 它實際上是兩個雙引號字符。

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

第一個命令中的$input變量也是如此,它應寫為:

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

如果要檢查對象中的空.errMsg值,則至少有兩個選項。

選項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的值成為實際值。 封閉的雙引號似乎只是出於您的目的。

您可以按如下方式將整個結構讀入本機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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM