JSON 올바른 구성

JSON 올바른 구성

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

관련 정보