셸 스크립트의 JSON 어레이를 통한 반복
data.json 파일에는 다음과 같은 JSON 데이터가 있습니다.
[
{"original_name":"pdf_convert","changed_name":"pdf_convert_1"},
{"original_name":"video_encode","changed_name":"video_encode_1"},
{"original_name":"video_transcode","changed_name":"video_transcode_1"}
]
배열을 반복하여 루프 내의 각 요소의 값을 추출합니다.jq 봤어요.나는 그것을 반복하는데 사용하는 것이 어렵다는 것을 안다.내가 어떻게 그럴 수 있을까?
배열의 각 항목을 반환하는 필터를 사용하십시오.후 출력 옵션(「 option」(「Compact output을 사용하고 있는 해 주세요.-c
따라서 각 결과는 1줄에 배치되어 루프 내의 1개의 항목으로 취급됩니다.
jq -c '.[]' input.json | while read i; do
# do stuff with $i
done
jq
셸.「 」 、 「 」 。@sh
.
다음을 사용하여 셸 매개 변수로 json 데이터의 형식을 지정할 수 있습니다.
cat data.json | jq '. | map([.original_name, .changed_name])' | jq @sh
출력은 다음과 같습니다.
"'pdf_convert' 'pdf_convert_1'"
"'video_encode' 'video_encode_1'",
"'video_transcode' 'video_transcode_1'"
각 행을 처리하려면 몇 가지 작업을 수행해야 합니다.
- bash for-loop을 첫 번째 공간에서 정지하지 않고 행 전체를 읽도록 설정합니다(기본 동작).
- 각 행을 처리하는 함수에 각 값을 매개 변수로 전달할 수 있도록 각 행에서 둘러싸인 이중 따옴표를 제거합니다.
for-loop의 행 bash for-loop을 합니다.IFS
변수(이 답변에서 설명한 바와 같이)입니다.
따옴표를 셸 인터프리터를 사용하여 bash 셸 xargs
:
stripped=$(echo $original | xargs echo)
이 모든 것을 종합하면, 다음과 같은 것이 있습니다.
#!/bin/bash
function processRow() {
original_name=$1
changed_name=$2
# TODO
}
IFS=$'\n' # Each iteration of the for loop should read until we find an end-of-line
for row in $(cat data.json | jq '. | map([.original_name, .changed_name])' | jq @sh)
do
# Run the row through the shell interpreter to remove enclosing double-quotes
stripped=$(echo $row | xargs echo)
# Call our function to process the row
# eval must be used to interpret the spaces in $stripped as separating arguments
eval processRow $stripped
done
unset IFS # Return IFS to its original value
Bash 어레이의 성능을 활용하면 다음과 같은 작업을 수행할 수 있습니다.
# read each item in the JSON array to an item in the Bash array
readarray -t my_array < <(jq --compact-output '.[]' input.json)
# iterate through the Bash array
for item in "${my_array[@]}"; do
original_name=$(jq --raw-output '.original_name' <<< "$item")
changed_name=$(jq --raw-output '.changed_name' <<< "$item")
# do your stuff
done
bash의 json 배열을 통해 반복(공백 포함)
items=$(echo "$JSON_Content" | jq -c -r '.[]')
for item in ${items[@]}; do
echo $item
# whatever you are trying to do ...
done
이 예제를 중심으로 구축해 보십시오.(출처:오리지널 사이트)
예:
jq '[foreach .[] as $item ([[],[]]; if $item == null then [[],.[0]] else [(.[0] + [$item]),[]] end; if $item == null then .[1] else empty end)]'
Input [1,2,3,4,null,"a","b",null]
Output [[1,2,3,4],["a","b"]]
여기 있는 어떤 대답도 나에게 통하지 않았다. 즉석에서.
몇 가지 조합이 효과가 있었습니다.
projectList=$(echo "$projRes" | jq -c '.projects[]')
IFS=$'\n' # Read till newline
for project in ${projectList[@]}; do
projectId=$(jq '.id' <<< "$project")
projectName=$(jq -r '.name' <<< "$project")
...
done
unset IFS
이에서는 example: 이음음음음음음음음음음음음음음음음음음음음음음음음음음음 note note note note note note note note note라고 가정합니다.projRes
는 JSON 입니다.예를 들어 JSON API 입니다.하다
{
"projects": [
{"id":1,"name":"Project"},
... // array of projects
]
}
jq를 사용하는 것이 되었습니다.foreach
하지만, 특히 정해진 임무를 고려할 때, 그것은 필요 이상으로 훨씬 더 복잡할 수 있다. 「」입니다.foreach
(그리고)reduce
)는를 축적할 가 있는 있습니다).
), '경감절단'을하는 것이 .[]
★★★★★★★★★★★★★★★★★」map(_)
후자는 [.[] | _]를 쓰는 또 다른 방법일 뿐이므로 jq를 사용하는 경우 .[]는 단순히 값의 스트림을 생성한다는 것을 이해하는 것이 매우 유용합니다.예를들면,[1,2,3] | .[]
는 3가지 값의 스트림을 생성합니다.
간단한 맵 축소 예를 들어 문자열 배열의 최대 길이를 찾는다고 가정합니다.한 가지 해결책은[ .[] | length] | max
.
다음은 zch 쉘에서 작동하는 간단한 예입니다.
DOMAINS='["google","amazon"]'
arr=$(echo $DOMAINS | jq -c '.[]')
for d in $arr; do
printf "Here is your domain: ${d}\n"
done
사용을 중지했습니다.jq
를 사용하기 시작했습니다.jp
JMESpath는 에 의해 사용되는 것과 같은 언어이기 때문에--query
두 언어를 동시에 구사하는 것은 어렵습니다.JMESpath 표현의 기본은 https://jmespath.org/tutorial.html에서 빠르게 배울 수 있습니다.
특별히 부탁하지 않으셨으니까jq
대답 대신 bash에서 JSON을 반복하는 접근방식이 적절한 답변이라고 생각합니다.
스타일 포인트:
- 나는 백틱을 사용하지만 그것들은 유행이 지났다.다른 명령 대체 연산자로 대체할 수 있습니다.
- 사용하고 있다
cat
입력 내용을 명령어에 파이프로 연결합니다.네, 파일명을 파라미터로 지정할 수도 있습니다만, 조작 순서를 왼쪽에서 오른쪽으로 읽을 수 없기 때문에 주의가 산만해집니다.물론 당신은 이것을 내 스타일에서 당신의 스타일로 업데이트 할 수 있습니다. set -u
이 솔루션에는 아무런 기능이 없지만 bash를 만지작거리고 있는 경우에는 중요합니다.명령어를 사용하면 변수를 강제로 선언할 수 있으므로 변수 이름의 철자를 틀릴 수 없습니다.
방법은 다음과 같습니다.
#!/bin/bash
set -u
# exploit the JMESpath length() function to get a count of list elements to iterate
export COUNT=`cat data.json | jp "length( [*] )"`
# The `seq` command produces the sequence `0 1 2` for our indexes
# The $(( )) operator in bash produces an arithmetic result ($COUNT minus one)
for i in `seq 0 $((COUNT - 1))` ; do
# The list elements in JMESpath are zero-indexed
echo "Here is element $i:"
cat data.json | jp "[$i]"
# Add or replace whatever operation you like here.
done
로컬 파일이 아닌 온라인 API에서 원본 JSON 데이터를 가져오는 것도 일반적인 사용 사례입니다.이 경우 전체 결과를 변수에 캐싱하는 약간 수정된 기술을 사용합니다.
#!/bin/bash
set -u
# cache the JSON content in a stack variable, downloading it only once
export DATA=`api --profile foo compute instance list --query "bar"`
export COUNT=`echo "$DATA" | jp "length( [*] )"`
for i in `seq 0 $((COUNT - 1))` ; do
echo "Here is element $i:"
echo "$DATA" | jp "[$i]"
done
이 두 번째 예에서는 데이터가 빠르게 변경되는 경우 반복하는 요소와 반복되는 데이터 내의 요소 간에 일관된 카운트가 보장된다는 이점이 있습니다.
이것이 지금까지 내가 해 온 일이다
arr=$(echo "$array" | jq -c -r '.[]')
for item in ${arr[@]}; do
original_name=$(echo $item | jq -r '.original_name')
changed_name=$(echo $item | jq -r '.changed_name')
echo $original_name $changed_name
done
언급URL : https://stackoverflow.com/questions/33950596/iterating-through-json-array-in-shell-script
'programing' 카테고리의 다른 글
반응 - 상태가 업데이트되지 않음 (0) | 2023.03.15 |
---|---|
TypeScript를 사용한 함수 파라미터의 소품 파괴 (0) | 2023.03.15 |
sysdate에서 년을 빼는 방법 (0) | 2023.03.15 |
Jackson 및 WebClient를 사용하여 json 어레이를 개체로 역직렬화 (0) | 2023.03.10 |
AngularJS에서 ngInclude 지시문에 모델을 지정하는 방법은 무엇입니까? (0) | 2023.03.10 |