jq 및 find를 사용하여 전제 조건과 일치하는 파일만 편집

jq 및 find를 사용하여 전제 조건과 일치하는 파일만 편집

속성과 버전이 다른 JSON 파일이 꽤 많이 있습니다. 특정 조건과 일치하는 파일만 수정하고 싶습니다. 후속작입니다find 및 jq를 사용한 내부 편집.

수백 개의 파일을 수정하고 PR을 열면 변경하고 싶은 것 외에는 아무것도 필요하지 않기 때문에 이것이 나에게 중요합니다. 예를 들어 들여쓰기를 변경하면 전체 파일이 변경된 것처럼 나타나 검토자가 실제 차이점을 확인하기 어렵습니다.

무슨 뜻인지 설명하기 위해 다음 두 파일을 이름이 지정된 폴더에 넣습니다 json.

{
    "identifier": "1",
    "version" : "1.0"
}

버전 뒤의 공백을 참고하세요. 이는 의도적인 것입니다.

{
    "identifier": "2",
    "version": "2.0"
}

이 조각의 들여쓰기는 공백 4개입니다(vscode의 기본값).

json 폴더를 가리키는 다음 스크립트를 실행합니다.

find json \
    -name '*.json' \
    -type f -exec sh -c '
    tmpfile=$(mktemp)
    for pathname do
        cp -- "$pathname" "$tmpfile" &&
        jq "select(.version == \"2.0\").identifier |= \"\"" <"$tmpfile" >"$pathname"
    done
    rm -f "$tmpfile"' sh {} +

내가 원하는 결과는 를 2.0제외한 버전의 파일만 수정된다는 것입니다 identifier. 최종 결과는 다음과 같습니다.

첫 번째 파일에는 원래 식별자(예상)가 있지만 들여쓰기가 이제 2개의 공백(예기치 않음)이고 다음 공백이 version사라졌습니다(예기치 않음).

{
  "identifier": "1",
  "version": "1.0"
}

두 번째 파일에는 빈 식별자(예상)가 있고 들여쓰기는 이제 2개의 공백입니다(예상치 않음).

{
  "identifier": "",
  "version": "2.0"
}

내가 아는 한 jq는 들여쓰기를 유지할 수 없으므로 질문의 범위를 제한하기 위해 일치하지 않는 버전의 파일을 영향을 받지 않게 유지하는 방법에만 관심이 있습니다.

grep위에 링크된 질문의 답변을 결합하여 이 문제를 해결 했지만 jq만 사용하는 더 효율적인 방법이 있을까요? 가능한 경우 원본 파일의 들여쓰기를 모두 유지하는 것이 이점입니다.

find json \
    -name '*.json' \
    -type f -exec sh -c '
    for pathname do
        if grep "\"version\": \"2.0\"" "$pathname" 1> /dev/null; then
            tmpfile=$(mktemp)
            cp -- "$pathname" "$tmpfile" &&
            jq "select(.version == \"2.0\").identifier |= \"\"" <"$tmpfile" >"$pathname"
            rm -f "$tmpfile"
        fi
    done' sh {} +

답변1

grepJSON 파일에서는 다음을 사용할 수 있습니다.일하다, 그러나 예상되는 형식의 파일에 따라 다릅니다. 또한, 일반적인 JSON 문서에서는 키의 순서가 고정되어 있지 않다는 점을 고려하면, identifier버전을 파악하면서 키의 null이 아닌 값을 테스트하는 것도 중요하다. 2.0그렇습니다. jq이 목적으로 사용하는 것이 가장 좋습니다.

이 작업은 변경해야 하는 JSON 파일에만 적용됩니다. 이 파일에는 version값이 있으며 2.0비어 identifier있지 않습니다.

를 사용하면 -e마지막 jq으로 평가된 표현식이 제공한 종료 상태로 종료할 수 있으며, 이를 사용하여 현재 파일이 수정될 것인지 여부를 테스트할 수 있습니다. 다음을 사용하여 any()선택한 입력 객체에 null이 아닌 값이 있는지 확인할 수 있습니다 identifier.

jq -e 'any(select(.version == "2.0"); .identifier != "")'

현재 JSON 문서에 수정이 필요한 경우 종료 상태가 0("성공")으로 종료됩니다.

명령의 일부로 find:

find json \
    -name '*.json' \
    -type f -exec sh -c '
    tmpfile=$(mktemp)
    for pathname do
        if jq -e "any(select(.version == \"2.0\"); .identifier != \"\")" "$pathname" >/dev/null
        then
            cp -- "$pathname" "$tmpfile" &&
            jq "select(.version == \"2.0\").identifier |= \"\"" <"$tmpfile" >"$pathname"
        fi
    done
    rm -f "$tmpfile"' sh {} +

어떤 파일이든 참고해주세요두 번째 통화는 jq다음으로 변경됩니다.고쳐 쓰기, 이는 identifier키 값 외에도 파일의 들여쓰기 및 기타 공백을 변경할 수 있음을 의미합니다. 파서의 관점에서 이는 JSON 문서에 영향을 미치지 않지만 JSON을 지원하지 않는 도구에서 보고된 파일에 대한 추가 변경을 유발할 수 있습니다.

--indent 4공백 4개를 들여 쓰기하여 JSON을 작성하려면 jq.

관련 정보