변수에 저장된 개체 목록이 포함된 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"
@sh
in 연산자 는 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로 파이프하는 것뿐입니다. 훌륭하게 작동하고 몇 가지 단계를 저장합니다.