jq를 사용하여 개행으로 구분된 4개의 json 파일 병합

jq를 사용하여 개행으로 구분된 4개의 json 파일 병합

4개의 JSON 파일을 병합하려고 합니다(향후에는 2개 더 추가될 수도 있음). 줄 바꿈으로 구분된 JSON 파일 간의 유일한 공통 요소는 "vulnid"입니다.

File 1: 
{"vulnid":"cve1", "product":"product1"}
{"vulnid":"cve2", "product":"product2"}
{"vulnid":"cve3", "product":"product3"}
{"vulnid":"cve4", "product":""}
{"vulnid":"cve5", "product":""}
{"vulnid":"cve6", "product":""}

File 2: 
{"vulnid":"cve1", "version":"version1"}
{"vulnid":"cve2", "version":"version2"}
{"vulnid":"cve3", "version":"version3"}
{"vulnid":"cve4", "version":"version4"}

File 3: 
{"vulnid":"cve1", "patch":"patch1"}
{"vulnid":"cve2", "patch":"patch2"}
{"vulnid":"cve3", "patch":"patch3"}
{"vulnid":"cve4", "patch":""}

File 4: 
{"vulnid":"cve1", "speed":"speed1"}
{"vulnid":"cve2", "power":"power2"}
{"vulnid":"cve3", "amps":"amps3"}
{"vulnid":"cve4", "product":"product4"}
{"vulnid":"cve4", "patch":"patch4"}


Required output:
{"vulnid":"cve1", "product":"product1", "version":"version1", "patch":"patch1", "speed":"speed1"}
{"vulnid":"cve2", "product":"product2", "version":"version2", "patch":"patch2", "power":"power2"}
{"vulnid":"cve3", "product":"product3", "version":"version3", "patch":"patch3", "amps":"amps3"}
{"vulnid":"cve4", "product":"product4", "version":"version4", "patch":"patch4"}
{"vulnid":"cve5", "product":""}
{"vulnid":"cve6", "product":""}

내가 지금까지 시도한 것 :

jq -s '.[0] * .[1] * .[3] * .[4]' json1 json2 json3 json4
jq -s '.[0] + .[1] + .[3] + .[4]' json1 json2 json3 json4

...그리고 jq의 다양한 조합은 모두 잘못된 결과를 제공하고 도구에 대해 내가 이해하지 못하는 점을 보여줍니다.

"vulnid" 및 jq 필드를 사용하여 이 병합을 수행할 수 있습니까?

답변1

가장 짧은jq해결책:

jq -sc 'group_by(.vulnid)[] | add' file*.json

산출:

{"vulnid":"cve1","product":"product1","version":"version1","patch":"patch1","speed":"speed1"}
{"vulnid":"cve2","product":"product2","version":"version2","patch":"patch2","power":"power2"}
{"vulnid":"cve3","product":"product3","version":"version3","patch":"patch3","amps":"amps3"}
{"vulnid":"cve4","product":"product4","version":"version4","patch":"patch4"}
{"vulnid":"cve5","product":""}
{"vulnid":"cve6","product":""}

답변2

네, 그런 것 같아요.

vulnid문자열을 키로 갖고 객체 자체를 해당 값(예: )으로 갖도록 데이터를 변경하면 및 를 사용하여 문자열을 동일한 키와 결합 할 {"cve1": {"vulnid": "cve1", "product": "product1" }}수 있습니다 . 아래의 첫 번째 것은 올바른 형식을 생성합니다 .reduce*map()reduce

따라서 파일의 예제 입력을 사용하면 다음과 같습니다 json.

$ < json jq -s 'map({(.vulnid): . }) | reduce .[] as $item ({}; . * $item) '
{
  "cve1": {
    "vulnid": "cve1",
    "product": "product1",
    "version": "version1",
    "patch": "patch1",
    "speed": "speed1"
  },
  ...

그런 다음 원하는 출력을 얻기 위해 개체 주위에 보풀을 배치하는 것이 매우 간단합니다.

$ < json jq -s 'map({(.vulnid): . }) | 
                    reduce .[] as $item ({}; . * $item) | map(.) | .[]'
{
  "vulnid": "cve1",
  "product": "product1",
  "version": "version1",
  "patch": "patch1",
  "speed": "speed1"
}
...

하지만 이 모든 것을 수행하는 더 좋은 방법이 있다고 해도 놀라지 않을 것입니다.

관련 정보