json 파일을 각 "keypath" 끝에 결과 값이 있는 "keypaths"로 변환합니다.

json 파일을 각 "keypath" 끝에 결과 값이 있는 "keypaths"로 변환합니다.

"grep"과 같은 간단한 도구를 사용하여 키 및/또는 값을 검색하려는 크고 비교적 복잡한 json 구성 파일이 있습니다. "grep"할 때 출력의 파일에 키에 대한 전체 경로와 최종 값으로 연결되는 각 하위 키/배열이 포함되기를 원합니다.

이는 대규모 파일 시스템에서 파일/디렉터리를 검색하고 "find" 명령을 사용하는 것처럼 파일/디렉토리가 발견되면 해당 파일/디렉터리의 전체 경로를 볼 수 있는 것과 유사합니다.

또한 제가 달성하려는 것과 유사한 비교는 더 쉬운 검색 및 보고를 위해 xml 파일을 키/값 경로로 변환하는 xml2 유틸리티입니다.

저는 "keys" 명령을 사용하여 json 파일을 구문 분석하기 위해 "jq" 유틸리티를 사용해 왔습니다. json 키 경로의 첫 번째 분기로 이동하는 조잡한 bash 스크립트를 작성했지만 json 구조의 전체 트리를 재귀적으로 위아래로 이동하는 쉬운 방법을 찾을 수 없습니다.

다음은 bash 스크립트에서 수행하려는 작업에 대한 수동 지침입니다. 네, 굉장히 비효율적이지만, 성능이 향상되기 전에는 해볼 수 있을 것 같아요!

복잡한 구성이 포함된 file.json이 주어지면 키를 사용하여 첫 번째 항목을 가져오고, 키를 얻은 후에는 이를 다른 반복에서 사용하여 다음 키를 가져오는 식으로 분기 끝에 도달할 때까지 계속합니다. ..

cat file.json | jq '. | keys | .[]'
cat file.json | jq '.Blueprints | keys | .[]'
cat file.json | jq '.Blueprints.security | keys | .[]'
cat file.json | jq '.Blueprints.security.kerberos_descriptor | keys | .[]'
cat file.json | jq '.Blueprints.security.kerberos_descriptor.identities | keys | .[]'

최종 결과는 다음과 같습니다.

."Blueprints"."security"."kerberos_descriptor"."identities"[0]."keytab"."configuration"."cluster-env/smokeuser_keytab"

그러나 물론 이것은 매우 큰 키/값 트리의 첫 번째 분기일 뿐입니다.

답변1

jq도움이 될 수 있는 몇 가지 적절한 내장 기능이 있습니다. Bash 기술이 많이 필요하지 않으며 이 문제를 해결하는 데 적합하지 않습니다. 이는 필요에 따라 수정할 수 있는 jq의 매우 명시적인 버전입니다.

jq -r '. as $root |
       path(..) | . as $path |
       $root | getpath($path) as $value |
       select($value | scalars) |
       ([$path[] | @json] | join(".")) + " = " + ($value | @json)
    ' < file.json

그것은 사용한다변수 바인딩 연산자... as $identifier |계산된 값을 이름으로 여러 번 기억하십시오. 그 중 일부는 불필요하지만 토론을 더 쉽게 만듭니다. 이 줄 각각은 프로그램의 나머지 부분의 변수를 $x왼쪽 값에 바인딩합니다.

이것path/1기능여기의 키이며 기본적으로 원하는 작업을 수행합니다. path(..)객체에 중첩된 각 값을 얻기 위해 반복해야 하는 모든 키가 포함된 배열을 생성합니다. 각 경로에는 다음과 같은 형식이 있습니다.

[ "Blueprints", "security", "kerberos_descriptor" ]

다른 배열과 동일한 방식으로 사용되며 경로를 해석하는 특수 함수와 함께 사용할 수도 있습니다.

path(..) | . as $path |

구체적으로 루프를 정의하십시오. 파일의 각 경로에 대해 루프를 호출 $path하고 나머지 프로그램을 루프 본문으로 실행하십시오. 프로그램의 나머지 부분은 선택과 출력이므로 각 경로에 대해 검사를 거쳐 출력 라인이 생성될 수도 있습니다.

getpath다음 경로 배열 중 하나를 읽으십시오.식별하는 값을 추출합니다.select필터링하자테스트를 통과한 값만 선택 - 여기서는 다음 기준을 만족하는 값만 선택스칼라(숫자, 문자열, 부울 또는 null)이므로 중간 객체와 배열은 무시됩니다(null 값도 마찬가지).

마지막 줄은 출력 형식을 다음과 같이 설정합니다.

"abc"."def".3."xyz" = true

파일의 각 값은 한 줄에 하나씩 있으며 필요에 따라 조정할 수 있습니다. 반복해서 찾아볼 수 있는 파일로 리디렉션하세요 grep.

@json값을 올바르게 인용하고 나머지는 필요한 형식에 맞게 쉽게 변경할 수 있어야 합니다. join다른 경우에 점으로 표시된 함수를 수동으로 복사하는 것은 매우 복잡하기 때문에 배열에 대괄호를 사용하지 않습니다 . 양쪽에 괄호가 필요합니다.

관련 정보