쉘 스크립트를 사용하여 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
이 점에서는 에코보다 더 도움이 됩니다. 과도한 중복을 방지하고 코드를 단축하려면 함수를 사용하세요.
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
. 대신 이 변형은 명령줄에서 허용되는 최대 길이로 제한되며 일반적으로 이 길이는 훨씬 더 작습니다. 장점은 이 최신 스크립트가 줄바꿈을 포함한 모든 문자가 포함된 값을 처리한다는 것입니다.