prosource

jq를 사용하여 2개의 파일에서 2개의 JSON 개체를 병합하려면 어떻게 해야 합니까?

probook 2023. 3. 14. 21:44
반응형

jq를 사용하여 2개의 파일에서 2개의 JSON 개체를 병합하려면 어떻게 해야 합니까?

셸 스크립트의 jq 툴(jq-json-processor)을 사용하여 json을 해석하고 있습니다.

2개의 json 파일을 가지고 있으며 하나의 고유한 파일로 병합하고 싶다.

파일 내용은 다음과 같습니다.

파일 1

{
    "value1": 200,
    "timestamp": 1382461861,
    "value": {
        "aaa": {
            "value1": "v1",
            "value2": "v2"
        },
        "bbb": {
            "value1": "v1",
            "value2": "v2"
        },
        "ccc": {
            "value1": "v1",
            "value2": "v2"
        }
    }
}

파일 2

{
    "status": 200,
    "timestamp": 1382461861,
    "value": {
        "aaa": {
            "value3": "v3",
            "value4": 4
        },
        "bbb": {
            "value3": "v3"
        },      
        "ddd": {
            "value3": "v3",
            "value4": 4
        }
    }
}

기대한 결과

{
    "value": {
        "aaa": {
            "value1": "v1",
            "value2": "v2",
            "value3": "v3",
            "value4": 4
        },
        "bbb": {
            "value1": "v1",
            "value2": "v2",
            "value3": "v3"
        },
        "ccc": {
            "value1": "v1",
            "value2": "v2"
        },
        "ddd": {
            "value3": "v3",
            "value4": 4
        }
    }
}

여러 가지 조합을 시도하지만 결과는 다음과 같습니다.이것은 기대했던 결과가 아닙니다.

{
  "ccc": {
    "value2": "v2",
    "value1": "v1"
  },
  "bbb": {
    "value2": "v2",
    "value1": "v1"
  },
  "aaa": {
    "value2": "v2",
    "value1": "v1"
  }
}
{
  "ddd": {
    "value4": 4,
    "value3": "v3"
  },
  "bbb": {
    "value3": "v3"
  },
  "aaa": {
    "value4": 4,
    "value3": "v3"
  }
}

다음 명령어 사용:

jq -s '.[].value' file1 file2

1.4 이후부터, 이것은,*교환입니다.2개의 오브젝트가 지정되면 재귀적으로 결합됩니다.예를들면,

jq -s '.[0] * .[1]' file1 file2

중요:주의:-s (--slurp)flag: 파일을 같은 배열에 저장합니다.

다음과 같은 이점을 얻을 수 있습니다.

{
  "value1": 200,
  "timestamp": 1382461861,
  "value": {
    "aaa": {
      "value1": "v1",
      "value2": "v2",
      "value3": "v3",
      "value4": 4
    },
    "bbb": {
      "value1": "v1",
      "value2": "v2",
      "value3": "v3"
    },
    "ccc": {
      "value1": "v1",
      "value2": "v2"
    },
    "ddd": {
      "value3": "v3",
      "value4": 4
    }
  },
  "status": 200
}

(예상했던 결과와 같이) 다른 키도 삭제하는 경우는, 다음의 방법으로 실행할 수 있습니다.

jq -s '.[0] * .[1] | {value: .value}' file1 file2

또는 (다른 값을 Marge하지 않기 때문에) 다소 더 효율적일 수 있습니다.

jq -s '.[0].value * .[1].value | {value: .}' file1 file2

사용하다jq -s add:

$ echo '{"a":"foo","b":"bar"} {"c":"baz","a":0}' | jq -s add
{
  "a": 0,
  "b": "bar",
  "c": "baz"
}

그러면 stdin에서 배열로 모든 JSON 텍스트가 읽힙니다(jq -s그렇게 되면, 「어쩔 수 없다」라고 하는 것입니다.

(add로 정의됩니다.def add: reduce .[] as $x (null; . + $x);입력 배열/개체 값을 반복하여 추가합니다.개체 추가 == 병합).

다음은 재귀적으로 작동하는 버전입니다(사용 방법:*임의의 개수의 오브젝트에 대해서:

echo '{"A": {"a": 1}}' '{"A": {"b": 2}}' '{"B": 3}' |\
  jq --slurp 'reduce .[] as $item ({}; . * $item)'

{
  "A": {
    "a": 1,
    "b": 2
  },
  "B": 3
}

아직 필요할지 누가 알겠습니까? 하지만 여기 해결책이 있습니다.

그 다음에--slurp옵션은 간단합니다!

--slurp/-s:
    Instead of running the filter for each JSON object in the input,
    read the entire input stream into a large array and run the filter just once.

그 다음에+operator는, 다음의 조작을 실시합니다.

jq -s '.[0] + .[1]' config.json config-user.json

(주의: 왼쪽 파일 개체를 오른쪽 파일 개체와 덮어쓰기만 하는 것이 아니라 내부 개체를 병합하려면 수동으로 해야 합니다.

지금까지의 솔루션이나 코멘트는 없습니다.input를 클릭하여 두 번째 파일에 액세스합니다.이를 채택하면 all-embracking 어레이와 같이 추출할 수 있는 추가 구조의 구축이 불필요해집니다.--slurp(또는-s) 옵션. 이 옵션은 다른 거의 모든 접근법에 적용됩니다.

2개의 파일을 최상위 레벨로 Marge 하려면 , 다음의 파일을 추가합니다.input의 선두에.사용.+:

jq '. + input' file1.json file2.json

모든 수준에서 두 파일을 재귀적으로 병합하려면 다음을 사용하여 동일한 작업을 수행합니다.*대신 연산자로:

jq '. * input' file1.json file2.json

즉, 두 개의 파일을 재귀적으로 병합하고 두 개의 오브젝트를 하나로 축소합니다.value필드, 먼저 필터링을 사용하여{value}:

jq '{value} * (input | {value})' file1.json file2.json
{
  "value": {
    "aaa": {
      "value1": "v1",
      "value2": "v2",
      "value3": "v3",
      "value4": 4
    },
    "bbb": {
      "value1": "v1",
      "value2": "v2",
      "value3": "v3"
    },
    "ccc": {
      "value1": "v1",
      "value2": "v2"
    },
    "ddd": {
      "value3": "v3",
      "value4": 4
    }
  }
}

데모

통합 에만 감소하는 솔루션은 다음과 같습니다.. * input | {value}코드는 짧아지지만, 「추출할 수 있는 추가 구조의 추가」를 다시 부활시켜, 최종적으로 부품이 커지면 대량의 오버헤드가 발생할 가능성이 있습니다.

하려면 , 2개의 파일 중 어느쪽인가를 합니다.input 번,으로 모든 것을 합니다.inputs''와 같이''는

jq 'reduce inputs as $i (.; . * $i)' file*.json

첫 은 항상 컨텍스트를 .. 동시에input(s)나머지 파일만 처리합니다(즉, 두 번째 파일부터 시작).--null-input ★★★★★★★★★★★★★★★★★」-n옵션이 주어집니다).

이 명령어는 명령어로 지정된 파일 수에 관계없이 병합할 수 있습니다.

jq -rs 'reduce .[] as $item ({}; . * $item)' file1.json file2.json file3.json ... file10.json

또는 임의의 개수의 파일에 대해

jq -rs 'reduce .[] as $item ({}; . * $item)' ./*.json

먼저 {"value": .value}는 단순히 {value}로 축약할 수 있습니다.

둘째, --argfile 옵션(jq 1.4 및 jq 1.5에서 사용 가능)은 --slurp 옵션을 사용할 필요가 없기 때문에 관심을 가질 수 있습니다.

이것들을 조합하면, 2개의 파일내의 2개의 오브젝트를 다음과 같이 지정된 방법으로 조합할 수 있습니다.

$ jq -n --argfile o1 file1 --argfile o2 file2 '$o1 * $o2 | {value}'

'-n' 플래그는 입력이 --argfile 옵션에서 나오기 때문에 stdin에서 읽지 않도록 jq를 지시합니다.

--argfile에 대한 주의사항

에서는 jq를 사용하지 않습니다.--argfile그 의미는 중요하지 않기 때문에 지정된 입력 파일에 정확히1개의 JSON 엔티티가 포함되어 있는 경우 해당 엔티티는 그대로 읽힙니다.그렇지 않은 경우 스트림 내의 항목은 배열로 래핑됩니다.

사용하는 몇 볼 수 .--argfile을 사용하는 것이 .그 때, 다음의 점에 주의해 주세요.--slurpfile비효율을 초래하지 않습니다.-s명령줄 옵션을 선택합니다.

개체에서 고유하지 않은 이전 키를 삭제하지 않으려는 경우

jq -n '{a:1, c:2}, {b:3, d:4}, {a:5,d:6}' |
jq -s 'map(to_entries)|flatten|group_by(.key)|map({(.[0].key):map(.value)|add})|add'
{
  "a": 6,
  "b": 3,
  "c": 2,
  "d": 10
}

값 값 후합니다.map(.value)|̶a̶d̶d̶

jq -n '{a:1, c:2}, {b:3, d:4}, {a:5,d:6}' |
jq -s 'map(to_entries)|flatten|group_by(.key)|map({(.[0].key):map(.value)})|add'
{
  "a": [1, 5],
  "b": [3],
  "c": [2],
  "d": [4, 6]
}

명령어의 각 부분을 제거하고 각 단계에서 개체 배열이 어떻게 변경되는지 확인하십시오.aka는 다음 단계를 실행하여 출력의 변화를 확인합니다.

map(to_entries)
map(to_entries)|flatten
map(to_entries)|flatten|group_by(.key)
map(to_entries)|flatten|group_by(.key)|map({(.[0].key):map(.value)})
map(to_entries)|flatten|group_by(.key)|map({(.[0].key):map(.value)})|add

언급URL : https://stackoverflow.com/questions/19529688/how-to-merge-2-json-objects-from-2-files-using-jq

반응형