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"
      }
    ]
  }
]

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

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

답변1

사용:

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

보다 집중적인 접근 방식이 필요한 경우:

readarray -td '' arr

개행이나 기타 특수 문자를 입력할 때 단어 분할을 피하세요.

산출:

value2
value2_2

확인하다:

임시 파일 이름으로 교체 >(command ...)또는 교체를 처리합니다. <(...)이 파일을 쓰거나 읽으면 바이트가 내부 명령으로 파이프됩니다. 일반적으로 파일 리디렉션과 함께 사용됩니다. cmd1 2> >(cmd2).seehttp://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"

@shin 연산자 는 jq쉘의 데이터를 올바르게 인용하도록 주의를 기울입니다.

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

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

이제 jq참조된 요소 목록만 생성된 다음 삽입되고 arr=( ... )평가됩니다.

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

답변4

Sputnick 덕분에 다음을 얻었습니다.

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

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

관련 정보