bash 배열을 채우는 데 사용된 for 루프의 결과를 zenity --progress에 파이프하면 왜 bash 배열이 여전히 비어 있습니까?

bash 배열을 채우는 데 사용된 for 루프의 결과를 zenity --progress에 파이프하면 왜 bash 배열이 여전히 비어 있습니까?

일부 데이터가 포함된 배열이 있습니다.

array1=( AAA BBB CCC DDD )

특정 API를 호출한 결과 배열을 데이터로 채우고 싶습니다. 그래서 다음과 같이 array1사용하려고 합니다 zenity.

i=0
prog=0

for c in ${array1[@]}; do
  echo $prog  #updates the text
  echo "# $c" #updates the percentage

  data_array[$i]=$(curl -s "https://hub.dummyapis.com/products?noofRecords=4&idStarts=1001&useless=$c" | jq .[$i].id | bc)

  (( prog=prog+30 ))
  (( i++ ))
done | zenity \
    --progress \
    --title="Title" \
    --text="Text" \
    --percentage=0 \
    --auto-close \
    --auto-kill

문제는 data_array아직 비어 있다는 것이다.

반면에 zenity명령에서 파이프를 생략하면 채워집니다. 내가 올바르게 이해했다면 파이프가 새로운 하위 프로세스를 생성하기 때문에 data_array비어 있기 때문입니다.

또한 이 구문을 사용해 보았으나 결과는 동일했습니다.

zenity \
    --progress \
    --title="Title" \
    --text="Text" \
    --percentage=0 \
    --auto-close \
    --auto-kill < <(
for c in ${array1[@]}; do
  echo $prog
  echo "# $c"

  data_array[$i]=$(curl -s "https://hub.dummyapis.com/products?noofRecords=4&idStarts=1001&useless=$c" | jq .[$i].id | bc)

  (( prog=prog+30 ))
  (( i++ ))
done)

어떡해?

답변1

파이프라인의 다양한 부분이 서브셸에서 실행됩니다. (Bash에서는 lastpipe마지막 부분이 기본 셸에서 실행되도록 하는 옵션을 활성화할 수 있지만 여기서는 도움이 되지 않습니다.) 프로세스 대체도 하위 셸에서 실행되지만 기본 부분이 동일한 작업을 수행하도록 강제하지는 않습니다.

zenity프로세스 교체를 넣고 for메인 셸에 보관하세요.

for c in ${array1[@]}; do
  ...
  data_array[$i]=...
  ...
done > >( zenity \
    --progress \
    --title="Title" \
    --text="Text" \
    --percentage=0 \
    --auto-close \
    --auto-kill )

답변2

또 다른 가능성: 첫 번째 예에서 교체

data_array[$i]=$(curl ... | jq ... | bc)

그리고

curl ... | jq ... | bc >> /tmp/so-q

코드 뒤에 다음을 추가하세요.

mapfile -t data_array < /tmp/so-q
rm /tmp/so-q
declare -p data_array

안전한 임시 파일을 생성하려면 mktemp를 사용할 수 있습니다. 바라보다 man mktemp.

답변3

아마도 이것은 가장 우아한 해결책은 아니지만 작동합니다.

tee이는 루프의 출력을 파일에 기록하고 zenity동시에 파일에 파이프하는 방식 에 의존합니다 .

위의 더미 코드를 사용하면 다음과 같습니다.

array1=( AAA BBB CCC DDD )

curl_cmd() {
  curl -s "https://hub.dummyapis.com/products?noofRecords=4&idStarts=1001&useless=$1" | jq .[$2].id | bc
}

i=0
prog=0

for c in ${array1[@]}; do
  #updates the text
  echo $prog
  #updates the percentage
  echo "# $c"

  #echo the data I'm interested in, 
  #with a @ for later reference
  echo "@ $(curl_cmd $c $i)" 

  (( prog=prog+30 ))
  (( i++ ))
done | tee >(zenity \
    --progress \
    --title="Title" \
    --text="Text" \
    --percentage=0 \
    --auto-close \
    --auto-kill) > /tmp/so-q

data_array=( $(grep @ /tmp/so-q | cut -c 2-) )

이제 data_array드디어 그 안에 사람이 살고 있다

~ $ echo ${data_array[@]}
1001 1002 1003 1004

관련 정보