를 사용하여 임의의 문서를 탐색하고 싶습니다 jq
. 이를 위해 jq
문서의 깊이를 제한하고 첫 번째 n
(가령 3) 수준 만 표시하고 싶습니다 .
다음 JSON 문서가 있다고 가정해 보겠습니다.
{
"a": {
"b": {
"c": {
"d": {
"e": "foo"
}
}
}
},
"f": {
"g": {
"h": {
"i": {
"j": "bar"
}
}
}
},
"k": {
"l": {
"m": {
"n": {
"o": "baz"
}
}
}
}
}
나는 결과를 기대한다
{
"a": {
"b": {
"c": {}
}
},
"f": {
"g": {
"h": {}
}
},
"k": {
"l": {
"m": {}
}
}
}
문서의 구조를 미리 알고 있다면 상당히 간단한 작업이지만 그렇지 않은 경우가 많습니다. 이것이 jq
바로 문서 구조의 처음 n개 수준만 표시 할 수 있기를 원하는 이유입니다 . 이는 사전과 배열이 임의로 중첩될 수 있습니다.
더 복잡한 예는 다음과 같습니다.
[
{ "a": { "b": { "c": { "d": { "e": "foo"}}}}},
{ "f": [ { "g": "foo"}]},
[ "h", "i", "j" ]
]
내가 결과를 기대하는 곳
[
{ "a": { "b": {}},
{ "f": [{}]},
[ "h", "i", "j" ]
]
내가 jq
이걸 할 수 있을까?
답변1
del
함수를 배열/객체 값 반복자와 결합하여 .[]?
네 번째 중첩 수준에서 키/값을 제거하면 원하는 결과를 얻을 수 있는 것 같습니다.
$ jq 'del(.[]?[]?[]?[]?)' <<'EOT'
[
{ "a": { "b": { "c": { "d": { "e": "foo"}}}}},
{ "f": [ { "g": "foo"}]},
[ "h", "i", "j" ]
]
EOT
[
{
"a": {
"b": {}
}
},
{
"f": [
{}
]
},
[
"h",
"i",
"j"
]
]
.[]?
배열이나 객체가 아닌 항목을 반복하려고 할 때 불만을 방지하려면 반복기 필터 버전이 필요합니다 ..[]
jq
솔직히 말해서 .[][]
문서 어디에서도 위에 표시된 형식(기본적으로: )의 배열/객체 반복자 필터에 대한 직접적인 언급을 찾을 수 없습니다. 덜 간결하지만 명확하게 문서화된 버전은 다음과 같습니다.
$ jq 'del(.[]? | .[]? | .[]? | .[]?)' ...
답변2
를 사용하면 path(..)
특정 문서에 대해 가능한 모든 경로 표현식을 생성할 수 있습니다. 그런 다음 select(length > 3)
예를 들어 너무 긴 것을 선택할 수 있습니다 . 로 삭제할 수 있습니다 delpaths()
.
jq
이는 단일 정수( with 로 전달할 수 있음 --argjson
) 로 쉽게 매개변수화할 수 있지만 path(..)
동시에 불필요하게 "무거운"(결과를 산출하는) 간결해 보이는 표현식을 작성할 수 있다는 장점이 있습니다.모든문서의 경로).
$ jq 'delpaths([path(..) | select(length > 3)])' file
{
"a": {
"b": {
"c": {}
}
},
"f": {
"g": {
"h": {}
}
},
"k": {
"l": {
"m": {}
}
}
}
질문 끝에 있는 예제 문서를 사용하여 테스트하세요.
$ jq . file
[
{
"a": {
"b": {
"c": {
"d": {
"e": "foo"
}
}
}
}
},
{
"f": [
{
"g": "foo"
}
]
},
[
"h",
"i",
"j"
]
]
$ jq --argjson d 1 'delpaths([path(..) | select(length > $d)])' file
[
{},
{},
[]
]
$ jq --argjson d 2 'delpaths([path(..) | select(length > $d)])' file
[
{
"a": {}
},
{
"f": []
},
[
"h",
"i",
"j"
]
]
$ jq --argjson d 3 'delpaths([path(..) | select(length > $d)])' file
[
{
"a": {
"b": {}
}
},
{
"f": [
{}
]
},
[
"h",
"i",
"j"
]
]
답변3
이 방법은 jq 버전마다 변경될 수 있는 공백에 의존하기 때문에 이상적이지 않을 수 있지만, 다른 도구를 사용하여 유사한 상황에 적용할 수 있다는 점에서는 강력한 방법입니다.
jq는 예쁜 인쇄를 완료한 후 json 트리 아래 요소 앞에 공백을 추가합니다. 따라서 특정 개수의 선행 공백이 있는 줄에서 역방향 grep을 수행하면 특정 깊이를 넘어서는 모든 요소를 제거할 수 있습니다. 아래 예에서는 귀하의 예와 유사하게 깊이가 4 이상인 요소를 제거했습니다.
grifball@grifball-Computer:~$ cat limit-output.json
{"a":{"b":{"c":{"d":{"e":"foo"}}}},"f":{"g":{"h":{"i":{"j":"bar"}}}},"k":{"l":{"m":{"n":{"o":"baz"}}}}}
grifball@grifball-Computer:~$ cat limit-output.json | jq
{
"a": {
"b": {
"c": {
"d": {
"e": "foo"
}
}
}
},
"f": {
"g": {
"h": {
"i": {
"j": "bar"
}
}
}
},
"k": {
"l": {
"m": {
"n": {
"o": "baz"
}
}
}
}
}
grifball@grifball-Computer:~$ cat limit-output.json | jq | grep -v '^\s\{8\}'
{
"a": {
"b": {
"c": {
}
}
},
"f": {
"g": {
"h": {
}
}
},
"k": {
"l": {
"m": {
}
}
}
}