키 없이(값만) 중첩 배열을 jq하고 csv로 변환하는 방법

키 없이(값만) 중첩 배열을 jq하고 csv로 변환하는 방법

누군가가 아래 json을 내가 기대하는 csv로 변환하는 방법을 안내해 줄 수 있기를 바랍니다.

미리 감사드립니다.

업데이트: 제공된 솔루션에 감사드립니다. 하지만 두 번째 열에 레코드가 1개만 있을 때 배열이 존재하지 않는 경우가 있습니다. 아래 예는 "unixhost1123"과 쌍을 이루는 레코드가 1개만 있는 "ASite"입니다.

소스 JSON

[
  {
    "results": [
      [
        "sm-clust001",
        [
          "163slesm02",
          "163slesm01"
        ]
      ],
      [
        "sm-cssl112",
        [
          "ucsbnchac240",
          "ucsbnchac209",
          "ucsbnchac241",
          "ucsbnchac242"
        ]
      ],
      [
        "ASite",
        "unixhost1123"
      ]
    ]
  }
]

CSV를 기대합니다

"sm-clust001","163slesm02"
"sm-clust001","163slesm01"
"sm-cssl112","ucsbnchac240"
"sm-cssl112","ucsbnchac209"
"sm-cssl112","ucsbnchac241"
"sm-cssl112","ucsbnchac242"
"ASite","unixhost1123"

답변1

.[].results[]배열의 집합입니다. 각 배열에서 첫 번째 요소는 첫 번째 열에 포함하려는 요소이고 두 번째 요소는 반복하려는 다른 배열입니다.

$name따라서 첫 번째 요소 (일종의 클러스터 이름이라고 가정) 를 추적 하고 하위 배열의 각 요소와 함께 출력해 보겠습니다.

.[].results[] | .[0] as $name | .[1][]? // .[1] | [ $name, . ] | @csv

이 비트는 .[1][]? // .[1]하위 배열의 요소가 있는 경우 선택되고, 그렇지 않으면 배열의 두 번째 요소가 선택됨을 나타냅니다(스칼라라고 가정).

명령줄에서:

jq -r '.[].results[] | .[0] as $name | .[1][]? // .[1] | [ $name, . ] | @csv' file

예제 문서의 결과를 보면 다음과 같습니다.

"sm-clust001","163slesm02"
"sm-clust001","163slesm01"
"sm-cssl112","ucsbnchac240"
"sm-cssl112","ucsbnchac209"
"sm-cssl112","ucsbnchac241"
"sm-cssl112","ucsbnchac242"
"ASite","unixhost1123"

이 솔루션은 여러 열에 적용됩니다.내 대답사용자에게후속 질문.

답변2

이것은 내가 아직 배우고 있는 가장 우아한 솔루션은 아닐 수도 있지만 jq원하는 결과를 얻을 수 있습니다.

jq -r '.[].results[] | { a:.[0], b:.[1][] } | [ .a, .b ] | @csv'

결과

"sm-clust001","163slesm02"
"sm-clust001","163slesm01"
"sm-cssl112","ucsbnchac240"
"sm-cssl112","ucsbnchac209"
"sm-cssl112","ucsbnchac241"
"sm-cssl112","ucsbnchac242"

"마법"은 두 번째 항목( )의 각 항목에 대해 { a:.[0], b:.[1][] }첫 번째 항목( )을 반복하는 파이프라인의 두 번째 부분에 있습니다. 그런 다음 이를 배열 목록으로 변환한 다음 CSV로 출력할 수 있습니다.[0][1][]

최근에 추가한 예제 데이터의 마지막 행을 처리하기 위해 파이프라인을 수정하여 이 이상값을 나머지 데이터와 동일한 모양으로 변환했습니다. (이것은 나에게도 학습 연습이었습니다.)

jq -r '
    .[].results[] |                     # Concentrate only on the results[] array
    [ .[0], [ .[1][]? // .[1] ] ] |     # Copy through first element; force the second to be an array
    { a:.[0], b:.[1][] } |              # Iterate across the second element as an array
    [ .a, .b ] |                        # Convert the objects we have just created back into array slices
    @csv                                # Output as CSV, remember the -r flag for jq
'

여기서 추가는 [ .[0], [ .[1][]? // .[1] ] ]구성 요소별로 이루어지며 각 블록의 첫 번째 요소를 그대로 전달하고 두 번째 요소는 다음과 같습니다.아니요배열은 이를 1로 변환합니다. (배열을 풀거나 싱글톤 항목을 렌더링하고 결과를 배열로 래핑합니다.)

또한지적(.[1][]? // .[1])이전과 같이 배열 요소를 반복하거나 단순히 배열이 아닌 경우 두 번째 요소를 제공하는 포함 if/then 표현식을 사용하여 원본 코드를 수정하여 보다 우아한 솔루션을 제공할 수 있습니다.

jq -r '.[].results[] | { a:.[0], b:(.[1][]? // .[1]) } | [ .a, .b ] | @csv'

수정 결과

"sm-clust001","163slesm02"
"sm-clust001","163slesm01"
"sm-cssl112","ucsbnchac240"
"sm-cssl112","ucsbnchac209"
"sm-cssl112","ucsbnchac241"
"sm-cssl112","ucsbnchac242"
"ASite","unixhost1123"

나는 그것으로부터 많은 것을 배웠다이 튜토리얼, 지금까지 찾은 것 중 최고 중 하나입니다.

관련 정보