JSON 파일의 경로와 키 값을 인쇄하는 방법

JSON 파일의 경로와 키 값을 인쇄하는 방법

각 경로와 값을 인쇄하고 싶습니다.키값을 한 줄씩 담은 파일입니다. 다음과 같은 상황을 고려하여그리고, 각 행의 값도 추가할 수 있나요? 사용하지 않는 경우다른 방법이 있나요? 나는 비슷한 것을 생각하고 있었다~을 위한. 또한, 내가 하려는 일에 대한 기술적인 용어가 있나요?

$ cat short.json | jq '.'
{
  "Reservations": [
    {
      "Groups": [],
      "Instances": [
        {
          "ImageId": "ami-a",
          "InstanceId": "i-a",
          "InstanceType": "t2.micro",
          "KeyName": "ubuntu"
        }
      ]
    }
  ]
}
$ cat short.json | jq -r '[paths | map(.|tostring) | join(".")]'
[
  "Reservations",
  "Reservations.0",
  "Reservations.0.Groups",
  "Reservations.0.Instances",
  "Reservations.0.Instances.0",
  "Reservations.0.Instances.0.ImageId",
  "Reservations.0.Instances.0.InstanceId",
  "Reservations.0.Instances.0.InstanceType",
  "Reservations.0.Instances.0.KeyName"
]

여러 줄 출력의 한 줄 예:
"Reservations.0.Instances.0.ImageId": "ami-a",

출력을 다음에서 사용할 수 있도록 포맷할 수 있다면 좋을 것입니다.복사 및 붙여넣기를 사용하면 Linux Cut을 사용하여 값을 쉽게 구분할 수 있습니다.

'.Reservations[].Instances[].ImageId': "ami-a" 
$ cat short.json | jq -r '.Reservations[].Instances[].ImageId'
ami-a

답변1

나는 이것에 대해 잘 모르지만 jq인터넷에서 이것을 찾았고 그것이 귀하의 경우에 적용된다고 생각합니다.

잘라내어 붙여넣기 버전:

jq -r 'paths(scalars | true) as $p  | [ ( [ $p[] | tostring ] | join(".") ), ( getpath($p) | tojson )] | join(": ")' short.json 

읽기 쉬운 버전:

jq -r '
paths(scalars | true) as $p
  | [ ( [ $p[] | tostring ] | join(".") )
    , ( getpath($p) | tojson )
    ]
  | join(": ")
' short.json

결과:

Reservations.0.Instances.0.ImageId: "ami-a"
Reservations.0.Instances.0.InstanceId: "i-a"
Reservations.0.Instances.0.InstanceType: "t2.micro"
Reservations.0.Instances.0.KeyName: "ubuntu"

보너스 포인트를 원하므로 sed다음 트릭을 사용하여 원하는 결과를 얻을 수 있습니다.

... | sed "s/^/\'./; s/:/\':/; s/\.0/[]/g"

어떤 출력:

'.Reservations[].Instances[].ImageId': "ami-a"
'.Reservations[].Instances[].InstanceId': "i-a"
'.Reservations[].Instances[].InstanceType': "t2.micro"
'.Reservations[].Instances[].KeyName': "ubuntu"

답변2

다음 jq표현식을 사용하여 출력의 키 부분과 값 부분이 모두 유효한 JSON인지 확인합니다(문자열인 경우 인코딩되고 따옴표 붙음, 부울, 숫자 또는 따옴표 없는 경우 따옴표 없음 null). kv_to_str읽기 쉽도록 키 값 문자열의 형식을 지정하는 도우미 함수를 만들었습니다 .

def kv_to_str($k; $v): "\($k): \($v)";

paths(scalars | true) as $p |
    kv_to_str(
        $p | join(".") | tojson;
        getpath($p) | tojson
    )

데이터에서 테스트해 보세요.

$ jq -r 'def kv_to_str($k;$v): "\($k): \($v)"; paths(scalars|true) as $p | kv_to_str($p|join(".")|tojson; getpath($p)|tojson)' file
"Reservations.0.Instances.0.ImageId": "ami-a"
"Reservations.0.Instances.0.InstanceId": "i-a"
"Reservations.0.Instances.0.InstanceType": "t2.micro"
"Reservations.0.Instances.0.KeyName": "ubuntu"

jq각 값에 대해 쿼리하는 표현식으로 사용할 수 있는 것을 얻으려면 "Reservations.0.Instances.0.ImageId"키를 생성할 필요가 없도록 약간의 조정을 수행할 수 있습니다 .["Reservations"][0]["Instances"][0]["ImageId"]. 거기에 0을 남겨두었으므로 배열 요소에 대해 보다 구체적인 키를 생성할 수 있습니다.

def kv_to_str($k; $v): "\($k): \($v)";

paths(scalars | true) as $p |
    kv_to_str(
        "." + ($p | map([.] | tojson) | join(""));
        getpath($p) | tojson
    )

키는 경로의 각 부분을 가져와서 [...]JSON으로 변환하여 생성됩니다(문자열은 따옴표로 묶이고 정수 인덱스는 따옴표 없이 유지됩니다). 그런 다음 조각을 연결하고 앞에 점을 추가합니다.

시험:

$ jq -r 'def kv_to_str($k;$v): "\($k): \($v)"; paths(scalars|true) as $p | kv_to_str("." + ($p|map([.]|tojson)|join("")); getpath($p)|tojson)' file
.["Reservations"][0]["Instances"][0]["ImageId"]: "ami-a"
.["Reservations"][0]["Instances"][0]["InstanceId"]: "i-a"
.["Reservations"][0]["Instances"][0]["InstanceType"]: "t2.micro"
.["Reservations"][0]["Instances"][0]["KeyName"]: "ubuntu"
$ jq -r '.["Reservations"][0]["Instances"][0]["InstanceType"]' file
t2.micro

관련 정보