쉘 스크립트를 사용하여 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
. 대조적으로, 이 변형은 일반적으로 훨씬 더 작은 명령줄의 최대 허용 길이로 제한됩니다. 장점은 이 최신 스크립트가 개행 문자를 포함한 모든 문자를 포함하는 값에 대처할 수 있다는 것입니다.