상위 쉘에서 하위 쉘의 변수를 사용 가능하게 만드는 방법

상위 쉘에서 하위 쉘의 변수를 사용 가능하게 만드는 방법

웹 서비스에서 일부 보고서의 시간을 측정하기 위해 빠르고 간단한 스크립트를 작성했습니다.

BASE_URL='http://example.com/json/webservice/'
FIRST=1
FINAL=10000

for report_code in $(seq 1 $FINAL); do
  (time -p response=$(curl --write-out %{http_code} --silent -O ${BASE_URL}/${report_code}) ) 2> ${report_code}.time

  echo $response  # <------- this is out of scope!  How do I fix that?
  if [[ $response = '404' ]]; then
    echo "Deleting report # ${report_code}!"
    rm ${report_code}
  else
    echo "${report_code} seems to be good!"
  fi
done

time출력을 리디렉션할 수 있도록 하위 쉘에서 명령을 래핑 해야 하지만 이로 인해 $response상위 쉘에서 값을 사용할 수 없게 됩니다. 이 문제를 어떻게 해결할 수 있나요?

답변1

오류가 발생하기 쉬운 마샬링 및 번거로운 통신 없이는 하위 쉘에서 상위 쉘로 변수 값을 전달할 방법이 없습니다.

다행히 여기에는 하위 쉘이 필요하지 않습니다. 리디렉션에는 다음 사항만 필요합니다.명령 그룹화을 사용하면 { … }서브쉘이 아닙니다.

{ time -p response=$(curl --write-out '%{http_code}' --silent -O "${BASE_URL}/${report_code}"); } 2> "${report_code}.time"

(잊지 마요변수 대체는 큰따옴표로 묶입니다..)

답변2

동료 U&L 사용자: main()C 스타일 함수 사용에 대한 내 답변을 반대하기 전에 다음 링크를 방문하세요.https://unix.stackexchange.com/a/313561/85039스크립트에서 주요 기능을 사용하는 것은 해당 분야의 많은 전문가들이 사용하는 일반적인 방법입니다.


Gilles가 지적했듯이 서브쉘은 환경 외부에서 변수를 사용할 수 없도록 만들 수 없습니다. 하지만 이를 다른 각도에서 접근해 보겠습니다. 함수에 스크립트를 작성하면 변수를 선언 local하고 편집할 수 있습니다.

Bash 4.3 매뉴얼에서 local설명:

...local이 함수 내에서 사용되면 변수 이름이 해당 함수와 해당 하위 함수에만 표시됩니다.

예:

#!/bin/bash

outter()
{
    for i in $(seq 1 3)
    do
        var=$i
    done
}

main()
{
    local var=0
    outter
    echo $var
}
main "$@"
$ ./testscript.sh                                                                                                        
3

보시다시피 루프 함수가 3번 반복된 후 변수가 수정됩니다.

답변3

a에서 변수를 리디렉션 test.txt하고 상위 셸에서 가져올 수 있습니다.

testfn()
{
echo "test" > test.txt # redirect your variable in a test.txt
}

testfn &       # execute your function in the subshell

testresult=$(cat test.txt) # get your variable in the parent shell
printf '%s\n' "$testresult"

답변4

bash 4.3부터 할 수 있습니다이름 참조 변수

#!/usr/bin/env bash

# outvar is a nameref variable that allows us to set the value of a variable 
# outside our scope
addfoo() {
   local x="$1"
   local -n outvar=$2

   x="foo$x"

   outvar="$x"
}

declare b=“loll”

addfoo "bar" b

echo "$b”

이는 foobar함수가 범위 밖에서 도 변수를 addfoo수정할 때 출력됩니다.bb

Nameref는 서브쉘을 사용하지 않고 함수에서 값을 추출하는 데 유용합니다 $(addfoo).

관련 정보