[英]create json from bash variable and associative array
假設我在 bash 中聲明了以下內容:
mcD="had_a_farm"
eei="eeieeio"
declare -A animals=( ["duck"]="quack_quack" ["cow"]="moo_moo" ["pig"]="oink_oink" )
我想要以下 json:
{
"oldMcD": "had a farm",
"eei": "eeieeio",
"onThisFarm":[
{
"duck": "quack_quack",
"cow": "moo_moo",
"pig": "oink_oink"
}
]
}
現在我知道我可以使用 echo、printf 或將文本分配給變量來做到這一點,但讓我們假設animals
實際上非常大,這樣做會很麻煩。 我還可以遍歷我的變量和關聯數組,並在這樣做時創建一個變量。 我可以編寫這些解決方案中的任何一個,但兩者似乎都是“錯誤的方式” 。 更不用說處理animals
的最后一項令人討厭,之后我不想要“,”。
我認為正確的解決方案使用 jq,但我很難找到關於如何使用此工具編寫 jsons(尤其是嵌套的 jsons)而不是解析它們的大量文檔和示例。
這是我想出的:
jq -n --arg mcD "$mcD" --arg eei "$eei" --arg duck "${animals['duck']}" --arg cow "${animals['cow']}" --arg pig "${animals['pig']}" '{onThisFarm:[ { pig: $pig, cow: $cow, duck: $duck } ], eei: $eei, oldMcD: $mcD }'
產生想要的結果。 實際上,我並不真正關心 json 中鍵的順序,但是 jq 的輸入必須倒退以按所需順序獲取它仍然很煩人。 無論如何,這個解決方案很笨拙,並且比簡單地聲明一個看起來像 json 的字符串變量(並且對於更大的關聯數組是不可能的)更容易編寫。 如何以高效、合乎邏輯的方式構建這樣的 json?
謝謝!
假設“animals”數組中的任何鍵或值都不包含換行符:
for i in "${!animals[@]}"
do
printf "%s\n%s\n" "${i}" "${animals[$i]}"
done | jq -nR --arg oldMcD "$mcD" --arg eei "$eei" '
def to_o:
. as $in
| reduce range(0;length;2) as $i ({};
.[$in[$i]]= $in[$i+1]);
{$oldMcD,
$eei,
onthisfarm: [inputs] | to_o}
'
注意{$x}
實際上擴展為{(x): $x}
的技巧
如果任何鍵或值包含換行符,您可以調整上述內容,以便使用 "\ " 作為分隔符:
for i in "${!animals[@]}"
do
printf "%s\0%s\0" "${i}" "${animals[$i]}"
done | jq -sR --arg oldMcD "$mcD" --arg eei "$eei" '
def to_o:
. as $in
| reduce range(0;length;2) as $i ({};
.[$in[$i]]= $in[$i+1]);
{$oldMcD,
$eei,
onthisfarm: split("\u0000") | to_o }
'
注意:以上假設 jq 版本為 1.5 或更高版本。
您可以使用for循環減少關聯數組並將其通過管道傳遞給jq
:
for i in "${!animals[@]}"; do
echo "$i"
echo "${animals[$i]}"
done |
jq -n -R --arg mcD "$mcD" --arg eei "$eei" 'reduce inputs as $i ({onThisFarm: [], mcD: $mcD, eei: $eei}; .onThisFarm[0] += {($i): (input | tonumber ? // .)})'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.