2017-10-09 78 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