我正在使用 shell 腳本生成 JSON 文件,但找不到自動刪除結尾“}”之前的最後一個逗號的解決方案。
這是我的程式碼:
echo "{" >> out_file
for i in 3 4 5 6 7 #ends at 298
do
y=$i
sommeMag=`awk -F '=' '/'$y'/{sommeMag+=$2}END{print sommeMag}'` "/myfolder/... "
store="mag$y"
if [ -z "$sommeMag" ] #checks is variable is empty
then
echo "\"" $store"\"":0",">> out_file
else
echo "\""$store"\"":$sommeMag"," >> out_file
fi
done
echo "}" >> out_file
該文件以這種方式結束:
{
" mag297":0,
" mag298":0, <-- syntaxt error
}
文件應該這樣結束:
{
...
" mag297":0,
" mag298":0 <-- no more comma
}
我該如何處理?
程式碼已經過編輯,以便在此處更具可讀性。
答案1
您應該做的是列印第一項,然後讓遊標停止。然後您可以開始處理循環並通過插入逗號和換行符來前進遊標。printf
在這方面比 echo 更有幫助。為了防止過度重複並縮短程式碼,請使用函數。
由於我沒有您用 awk 解析的文件,因此我無法使用您的腳本,但下面的範例說明了我想要傳達的內容。
#!/bin/bash
print_entry(){
# sommeMag would be variable $2, $1 is store
if [ -z $2 ]
then
printf '"%s":0' "$1"
else
printf '"%s":%s' "$1" "$2"
fi
}
# main part of the script
printf "%s\n" "{"
# do the first one unconditionally but without comma
print_entry "something1" "something2"
for i in 2 3 4 5
do
# because first one was printed unconditionally
# now we just keep printing comma and moving cursor
# to newline to insert the new entry
printf ",\n"
print_entry "something$i" "$i"
done
printf "\n%s" "}"
樣品運行
$ ./make_json.sh
{
"something1":something2,
"something2":2,
"something3":3,
"something4":4,
"something5":5
}$
上述方法通常就是我所說的「在後面加上逗號」。另一種方法是“在前面加上逗號”,但不是使用 for 循環,而是使用while
帶有計數器的循環來模擬 C 風格的 for 循環行為。如果到達最後一項,請不要輸出逗號。基本上
counter=1
while [ $counter -le 298 ]
do
$json_value=$(command1)
if [ $counter -ne 298 ]
then
echo $json_value ,
else
echo $json_value
fi
$counter=$(($counter+1))
done
答案2
#
# var initialzizations
#
# newline
NL=`printf '\nn'`;NL=${NL%?}
# double quote
q=\"
# separator set to a comma+newline
sep=",$NL"
# container for the json result
json=;
# begin/end of count values
start=3
stop=7
# looping
# in case seq utility not found, then you can use: yes | sed -ne "$start,$stop=;${stop}q"
for i in `seq "$start" "$stop"`
do
y=$i
sommeMag=`awk -F = "/$y/"'{sommeMag+=$2}END{print sommeMag}'` "/myfolder/... "
store=mag$y
json=${json:-}${json:+"$sep"}$q\ $store$q:${sommeMag:-0}
done
# remove the separtor from the end and also place a newline
json=${json%"$sep"}$NL
printf '{\n%s}\n' "$json" >> out_file
答案3
給定一個製表符分隔的鍵和值對流,建構一個包含這些鍵和值的 JSON 物件。 (如果資料包含實際製表符,只需使用不屬於資料的字元即可。)
for something something
do
output key and value with a tab in-between
done |
jq -Rn 'reduce inputs as $line ({}; ($line|split("\t")) as [$key, $value] | . += {($key): $value})'
這用於jq
讀取行流,每行都有一個由製表符分隔的鍵和值。每一行都以表達式$line
中的方式讀取和使用jq
。它在製表符上進行分割,並將鍵和值添加到語句reduce
正在累積的物件中。隨著新鍵和值的添加,物件不斷增長,並且當輸入流結束時,將輸出完成的物件。
這是該表達式的一個漂亮的列印版本jq
:
reduce inputs as $line ({};
($line | split("\t")) as [$key, $value] |
. += {($key): $value}
)
一個工作範例腳本:
#!/bin/bash
for (( i = 1; i <= 10; ++i ))
do
printf 'key%.2d\tvalue%.2d\n' "$i" "$i"
done |
jq -Rn 'reduce inputs as $line ({}; ($line|split("\t")) as [$key, $value] | . += {($key): $value})'
輸出:
{
"key01": "value01",
"key02": "value02",
"key03": "value03",
"key04": "value04",
"key05": "value05",
"key06": "value06",
"key07": "value07",
"key08": "value08",
"key09": "value09",
"key10": "value10"
}
如果沒有太多的鍵和值,我們可以簡化這一點,只需建立一個很長的jq
命令行,使用 將每個鍵與其值關聯起來--arg
,然後要求jq
輸出這些(可以在內部$ARGS.named
結構中找到):
#!/bin/bash
args=()
for (( i = 1; i <= 10; ++i ))
do
printf -v key 'key%.2d' "$i"
printf -v value 'value%.2d' "$i"
args+=( --arg "$key" "$value" )
done
jq -n "${args[@]}" '$ARGS.named'
在這種情況下,輸出將與先前腳本的輸出相同。不同之處在於,早期腳本可以處理的鍵和值的數量受到進程可用記憶體的限制jq
。相反,此變體受到命令列允許的最大長度的限制,該長度通常要小得多。從好的方面來說,這個最新的腳本將處理包含任何字元的值,包括換行符。