
변수에 저장된 개체 목록이 포함된 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
사용jq:
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"
연산자 @sh
는 jq
쉘에 대한 데이터를 적절하게 인용하도록 주의를 기울입니다.
또는 해당 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로 파이프하는 것뿐입니다. 훌륭하게 작동하고 일부 단계를 저장했습니다.