나는 다음 Stackexchange 기사의 아이디어를 따랐습니다.
그런데 선택하고 추가할 때 따옴표에 문제가 있습니다.
내 샘플 json 파일은 다음과 같습니다.
{
"options": [
{
"label": "22",
"value": "2022"
},
{
"label": "23",
"value": "2023"
}
]
}
이것은 내 테스트 bash 스크립트입니다.
#!/bin/bash
previous_year=$(date --date="$(date +'%Y') - 1 year" +%Y)
last_year=$((previous_year + 31))
label=$((last_year -2000))
echo ${last_year}
jq 'del(.options[]? | select(.label == \"${previous_year}\"))' temp.json
jq '.options += [{
"label": '${label}',
"value": '${last_year}'
}]' temp.json
이 샘플 파일을 사용하여 bash 스크립트를 실행하면 jq: error: Syntax error, Unexpected INVALID_CHARACTER (Unix shell quoteing issue?) at , line 1: del(.options[]? | select(.label == "$)이 발생합니다. { 이전_연도}"))
jq: 1 컴파일 오류
"를 제거하면 실행되지만 따옴표가 없는 것처럼 보이므로 제거할 항목을 찾을 수 없습니다. 또한 요소를 배열에 추가하지만 따옴표는 추가하지 않습니다.
어떻게 해야 합니까?
- 따옴표가 있는 요소 찾기
- 인용된 요소 추가
예상 결과(내가 달성하고 싶은 것)는 다음과 같습니다.
{
"options": [
{
"label": "23",
"value": "2023"
},
{
"label": "53",
"value": "2053"
}
]
}
답변1
label
셸 변수에 올바른 값이 있고 해당 값을 가진 배열의 모든 항목을 삭제 last_year
하고 해당 값과 값을 가진 새 항목을 추가한다고 가정합니다 .previous_year
options
value
$previous_year
label
$label
value
$last_year
jq --arg add_label "$label" \
--arg add_value "$last_year" \
--arg del_value "$previous_year" '
del(.options[]? | select(.value == $del_value)) |
.options += [{ label: $add_label, value: $add_value }]' file
이는 한 번의 호출로 두 가지 작업을 올바르게 결합합니다 jq
.
이 명령은 jq
이전에 생성한 셸 변수에서 얻은 값을 사용하여 세 개의 내부 문자열 변수를 인스턴스화합니다. --arg
셸 변수에서 생성된 내부 문자열 변수를 사용하면 값이 올바르게 인코딩되도록 보장됩니다(이렇게 하면 코드 삽입 취약점을 방지할 수 있습니다).
귀하의 코드에서와 마찬가지로 배열이 존재하지 않는 경우 오류를 .options[]?
피하기 위해 대신 사용합니다 . 존재하는 경우 값이 (쉘 변수의 값을 갖는 내부 변수)인 항목은 제거됩니다 . select를 사용해 보셨지만 오타일 수도 있다고 생각합니다..options[]
options
value
$del_value
previous_year
label
(아마도) 수정된 문서는 다음 단계로 전달되어 배열에 새 요소가 추가됩니다 options
. 배열이 이전에 존재하지 않은 경우 단일 요소로 생성됩니다.
또한 jq
내부 편집을 수행하지 않으므로 위 명령의 출력을 새 이름으로 리디렉션한 다음 원본 파일을 해당 새 파일로 바꿔야 함을 의미합니다. 또는 GNU를 사용하십시오 sponge
.
jq ...as above... file | sponge file
(파일 이름은 이라고 가정합니다 file
.)
답변2
#!/bin/bash
file=temp.json
now="$(date)"
previous_year=$(date --date="$(date +'%Y') - 1 year" +%Y)
last_year=$((previous_year + 31))
label=$((last_year -2000))
echo "==============================================================================================================="
echo "| Started parsing json file at script at: $file"
echo "| Started at: $now"
echo "| previous year is: $previous_year"
echo "| last year to be at json array is: $last_year"
echo "| label assigned to the last year : $label"
echo "==============================================================================================================="
if cat $file | grep $previous_year
then
jq --arg key "$previous_year" 'del(.options[] | select(.value == $key))' $file >> new.json
jq --arg key "$label" --arg val "$last_year" '.options += [{
"label": $key,
"value": $val
}]' new.json >> new2.json
mv new2.json $file
rm new.json
echo "last year found and parsed"
else
echo "nothing to be done"
fi
now="$(date)"
echo "==============================================================================================================="
echo "| Ended script at: $now"
echo "==============================================================================================================="
´´´