이 파일이 주어지면:
$ cat fruits.json
[
{ "name": "apple" },
{ "name": "banana\nfofanna" },
{ "name": "my kiwi" }
]
jq
예를 들어 배열을 채우기 위해 쉘이 데이터로 사용하는 과일 이름 목록을 검색하는 데 이것을 어떻게 사용할 수 있습니까 ?
fruits
다음 배열 할당 과 동일합니다 .
$ fruits=(
'apple'
'banana
fofanna'
'my kiwi'
)
$ for f in "${fruits[@]}" ;do echo "<$f>"; done
<apple>
<banana
fofanna>
<my kiwi>
다음 중 어느 것도 유효하지 않습니다.
$ fruits=( $(jq -r ' .[].name ' fruits.json))
$ fruits=( $(jq -r ' .[].name | @sh ' fruits.json))
$ fruits=( $(jq ' .[].name | @sh ' fruits.json))
답변1
질문 끝의 처음 두 시도는 jq
공백으로 출력을 분할하는 쉘에 의존하기 때문에 작동하지 않습니다. 줄 바꿈은 일종의 공백이므로 데이터에서 줄 바꿈(탭 및 원시 공백 포함)이 손실됩니다.
또한 이러한 시도는 문자열 데이터를 참조할 수 없으므로 문자열에 파일 이름 와일드카드가 포함된 경우 파일 이름 와일드카드를 얻게 됩니다.
비슷한 이유로 마지막 시도가 실패했지만 추가로 데이터를 올바르게 디코딩하지 못해 인코딩된 줄 바꿈이 그대로 유지되었습니다.
내장 연산자 @sh
in 을 사용하여 jq
데이터를 참조하고 배열 할당을 구성합니다.
eval "$( jq -r '"fruits=(" + (map(.name)|@sh) + ")"' fruits.json )"
주어진 JSON 데이터에 대해 현재 쉘이 다음 할당을 평가하여 배열을 생성하게 됩니다 fruits
.
fruits=('apple' 'banana
fofanna' 'my kiwi')
이 진술을 평가한 후,
$ printf '<%s>\n' "${fruits[@]}"
<apple>
<banana
fofanna>
<my kiwi>
대안으로, 다음은추가의name
쉘 배열의 각 요소 값:
$ jq -r '"fruits+=(" + (.[].name | @sh) + ")"' fruits.json
fruits+=('apple')
fruits+=('banana
fofanna')
fruits+=('my kiwi')
$ unset -v fruits
$ eval "$(jq -r '"fruits+=(" + (.[].name | @sh) + ")"' fruits.json)"
$ printf '<%s>\n' "${fruits[@]}"
<apple>
<banana
fofanna>
<my kiwi>
답변2
ZSH에 어떤 쉘을 사용할 것인지 언급하지 않았습니다.
% fru=( ${(fQg::)"$(jq '.[].name' ~/tmp/fru)"} )
% for f in $fru; printf '<%s>\n' $f
<apple>
<banana
fofanna>
<my kiwi>
% =echo -n "<${fru[2]}>" | od -bc
0000000 074 142 141 156 141 156 141 012 146 157 146 141 156 156 141 076
< b a n a n a \n f o f a n n a >
0000020
jq
호출을 수행 한 다음 f
결과를 줄 바꿈으로 분할하고 출력에서 문자열에 남은 따옴표를 제거합니다 Q
.jq
g::
보간을 수행하기 위해 내장된 에코처럼 작동합니다.\n
입력의 문자열에.
답변3
@Kusalananda, @roaima 및 @StéphaneChazelas의 답변과 의견을 바탕으로위 댓글에 언급된 비슷한 질문, 나는 다음을 알아낼 수 있었습니다:
list=$( jq -r ' .[].name | @sh ' fruits.json ) || exit 1
eval "fruits=( $list )" || exit 1
printf "<%s>\n" "${fruits[@]}"