공백을 고려하여 jq를 사용하여 정보를 쉘에 반환하려면 어떻게 해야 합니까?

공백을 고려하여 jq를 사용하여 정보를 쉘에 반환하려면 어떻게 해야 합니까?

이 파일이 주어지면:

$ 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공백으로 출력을 분할하는 쉘에 의존하기 때문에 작동하지 않습니다. 줄 바꿈은 일종의 공백이므로 데이터에서 줄 바꿈(탭 및 원시 공백 포함)이 손실됩니다.

또한 이러한 시도는 문자열 데이터를 참조할 수 없으므로 문자열에 파일 이름 와일드카드가 포함된 경우 파일 이름 와일드카드를 얻게 됩니다.

비슷한 이유로 마지막 시도가 실패했지만 추가로 데이터를 올바르게 디코딩하지 못해 인코딩된 줄 바꿈이 그대로 유지되었습니다.


내장 연산자 @shin 을 사용하여 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.jqg:: 보간을 수행하기 위해 내장된 에코처럼 작동합니다.\n입력의 문자열에.

답변3

@Kusalananda, @roaima 및 @StéphaneChazelas의 답변과 의견을 바탕으로위 댓글에 언급된 비슷한 질문, 나는 다음을 알아낼 수 있었습니다:

list=$( jq -r ' .[].name | @sh ' fruits.json ) || exit 1
eval "fruits=( $list )" || exit 1
printf "<%s>\n" "${fruits[@]}"

관련 정보