JSON 배열의 한 필드를 bash 배열로 구문 분석합니다.

JSON 배열의 한 필드를 bash 배열로 구문 분석합니다.

변수에 저장된 개체 목록이 포함된 JSON 출력이 있습니다. (제가 표현한 것이 맞을지도 모르겠습니다)

[
  {
    "item1": "value1",
    "item2": "value2",
    "sub items": [
      {
        "subitem": "subvalue"
      }
    ]
  },
  {
    "item1": "value1_2",
    "item2": "value2_2",
    "sub items_2": [
      {
        "subitem_2": "subvalue_2"
      }
    ]
  }
]

bash 스크립트를 우분투 14.04.1에서 실행하려면 배열의 item2에 대한 모든 값이 필요합니다.

필요한 항목뿐만 아니라 전체 결과를 배열로 가져오는 여러 가지 방법을 찾았습니다.

답변1

사용:

readarray arr < <(jq '.[].item2' json)
printf '%s\n' "${arr[@]}"

좀 더 강화된 방법이 필요한 경우:

readarray -td '' arr

줄 바꿈이나 기타 특수 문자가 포함된 입력의 경우 단어 분할을 방지합니다.

산출:

value2
value2_2

확인하다:

프로세스 대체 >(command ...)또는 <(...)임시 파일 이름으로 대체됩니다. 해당 파일을 쓰거나 읽으면 바이트가 내부 명령으로 파이프됩니다. 종종 파일 리디렉션과 함께 사용됩니다: cmd1 2> >(cmd2). 보다http://mywiki.wooledge.org/ProcessSubstitution http://mywiki.wooledge.org/BashFAQ/024

답변2

다음은 실제로 버그가 있습니다.

# BAD: Output line of * is replaced with list of local files; can't deal with whitespace
arr=( $( curl -k "$url" | jq -r '.[].item2' ) )

bash 4.4 이상을 사용하는 경우 세계 최고의 옵션을 사용할 수 있습니다.

# BEST: Supports bash 4.4+, with failure detection and newlines in data
{ readarray -t -d '' arr && wait "$!"; } < <(
  set -o pipefail
  curl --fail -k "$url" | jq -j '.[].item2 | (., "\u0000")'
)

...bash 4.0을 사용하면 오류 감지 및 문자 그대로 개행 지원을 희생하여 간결해질 수 있습니다.

# OK (with bash 4.0), but can't detect failure and doesn't support values with newlines
readarray -t arr < <(curl -k "$url" | jq -r '.[].item2' )

...또는 bash 3.x 호환성 및 오류 감지(개행 지원 없음):

# OK: Supports bash 3.x; no support for newlines in values, but can detect failures
IFS=$'\n' read -r -d '' -a arr < <(
  set -o pipefail
  curl --fail -k "$url" | jq -r '.[].item2' && printf '\0'
)

...또는 bash 3.x 호환성 및 개행 지원(실패 감지 없음):

# OK: Supports bash 3.x and supports newlines in values; does not detect failures
arr=( )
while IFS= read -r -d '' item; do
  arr+=( "$item" )
done < <(curl --fail -k "$url" | jq -j '.[] | (.item2, "\u0000")')

답변3

jq평가할 쉘 문을 생성하는 데 사용됩니다 .

eval "$( jq -r '@sh "arr=( \([.[].item2]) )"' file.json )"

질문에 JSON 문서가 있는 경우 호출하면 jq문자열이 생성됩니다.

arr=( 'value2' 'value2_2' )

그런 다음 쉘에서 평가됩니다. 해당 문자열을 평가하면 arr두 요소 value2와 다음을 포함하는 명명된 배열이 생성됩니다 value2_2.

$ eval "$( jq -r '@sh "arr=( \([.[].item2]) )"' file.json )"
$ printf '"%s"\n' "${arr[@]}"
"value2"
"value2_2"

연산자 @shjq쉘에 대한 데이터를 적절하게 인용하도록 주의를 기울입니다.

또는 해당 arr=( ... )부분을 표현식 밖으로 이동합니다 jq.

eval "arr=( $( jq -r '@sh "\([.[].item2])"' file.json ) )"

이제는 jq인용된 요소 목록만 생성한 다음 삽입 arr=( ... )하고 평가합니다.

명령 에서 데이터를 읽어야 하는 경우 위 명령 대신에 를 curl사용하세요 .curl ... | jq -r ...jq -r ... file.json

답변4

스푸트니크 덕분에 나는 이것을 얻었습니다:

arr=( $(curl -k https://localhost/api | jq -r '.[].item2') )

내가 가지고 있는 JSON은 API의 출력입니다. 내가 해야 할 일은 파일 인수를 제거하고 |컬의 출력을 jq로 파이프하는 것뿐입니다. 훌륭하게 작동하고 일부 단계를 저장했습니다.

관련 정보