[英]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.