jq를 사용하여 배열에 JSON 객체 추가

jq를 사용하여 배열에 JSON 객체 추가

jq내 목표는 bash의 명령 출력을 사용하여 JSON 개체를 출력하는 것입니다. find한 줄 명령일 수도 있고 bash 스크립트일 수도 있습니다.

각 출력 줄에서 JSON 개체를 생성하는 다음 명령이 있습니다.

find ~/ -maxdepth 1 -name "D*" | \
while read line; \
do jq -n \
--arg name "$(basename "$line")" \
--arg path "$line" \
'{name: $name, path: $path}'; \
done

출력은 다음과 같습니다.

{
  "name": "Desktop",
  "path": "/Users/username/Desktop"
}
{
  "name": "Documents",
  "path": "/Users/username/Documents"
}
{
  "name": "Downloads",
  "path": "/Users/username/Downloads"
}

하지만 이러한 객체가 배열에 있어야 하고 해당 배열이 items다음과 같이 상위 객체의 단일 키 값이 되도록 해야 합니다.

{"items": [
    {
      "name": "Desktop",
      "path": "/Users/username/Desktop"
    },
    {
      "name": "Documents",
      "path": "/Users/username/Documents"
    },
    {
      "name": "Downloads",
      "path": "/Users/username/Downloads"
    }
  ]
}

jq각 줄의 출력 문자열에 대괄호를 추가하고( '[{name: $name, path: $path}]';) 대괄호를 추가 했지만 배열 요소 사이에 쉼표는 추가하지 않았습니다.

가능한 해결책을 찾았습니다여기하지만 각 행을 반복하면서 사용하는 방법을 모르겠습니다.

답변1

jq 1.5 inputs스트리밍 필터 트릭이 효과가 있는 것 같습니다.

... | jq -n '.items |= [inputs]'

전임자.

$ find ~/ -maxdepth 1 -name "D*" | 
    while read line; do 
      jq -n --arg name "$(basename "$line")" \
            --arg path "$line" \
        '{name: $name, path: $path}'
    done | jq -n '.items |= [inputs]'
{
  "items": [
    {
      "name": "Downloads",
      "path": "/home/steeldriver/Downloads"
    },
    {
      "name": "Desktop",
      "path": "/home/steeldriver/Desktop"
    },
    {
      "name": "Documents",
      "path": "/home/steeldriver/Documents"
    }
  ]
}

답변2

jq호출에서 직접 find결과 데이터를 사용하여 jq셸 루프 없이 최종 출력을 빌드합니다.

find ~ -maxdepth 1 -name '[[:upper:]]*' \
    -exec jq -n --arg path {} '{ name: ($path|sub(".*/"; "")), path: $path }' \; |
jq -n -s '{ items: inputs }'

발견된 각 경로 이름에 대해 JSON 개체를 생성하여 실행됩니다 jq. -exec값의 마지막 슬래시까지 경로 이름의 모든 내용을 제거 name하고 경로 이름을 그대로 값으로 사용합니다 path.

마지막으로 jq데이터를 find배열 로 읽은 -s다음 items새 JSON 개체에 배열로 삽입합니다. 최종 jq호출은 다음과 같이 작성할 수도 있습니다 jq -n '{ items: [inputs] }.

[[:upper:]*결과 예( 대체 패턴을 사용하고 있음에 유의하세요 D*):-namefind

{
  "items": [
    {
      "name": "Documents",
      "path": "/home/myself/Documents"
    },
    {
      "name": "Mail",
      "path": "/home/myself/Mail"
    },
    {
      "name": "Work",
      "path": "/home/myself/Work"
    }
  ]
}

답변3

프로그래밍 언어를 사용하는 것이 마음에 들지 않는다면 매우 간단합니다. 다음은 PHP 예제입니다:

<?php
$m1 = [
   'items' => []
];
$a1 = glob('~/D*');
foreach ($a1 as $s1) {
   $m1['items'][] = [
      'name' => basename($s1),
      'path' => $s1
   ];
}
echo json_encode($m1, JSON_PRETTY_PRINT);

관련 정보