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이 점에서는 에코보다 더 도움이 됩니다. 과도한 중복을 방지하고 코드를 단축하려면 함수를 사용하세요.

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. 대신 이 변형은 명령줄에서 허용되는 최대 길이로 제한되며 일반적으로 이 길이는 훨씬 더 작습니다. 장점은 이 최신 스크립트가 줄바꿈을 포함한 모든 문자가 포함된 값을 처리한다는 것입니다.

관련 정보