부모 셸에서 사용 가능한 서브 쉘의 변수를 만드는 방법


11

웹 서비스에서 일부 보고서를 작성하는 빠르고 더러운 스크립트를 작성했습니다.

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쉘로 랩핑해야 하지만 이는 상위 쉘 에서 사용할 수없는 값을 만듭니다 . 이 문제를 어떻게 해결합니까?

답변:


11

오류가 발생하기 쉬운 마샬링 및 번거로운 통신을 수행하지 않으면 서 서브 쉘에서 부모로 변수 값을 가져올 수 없습니다.

다행히도 여기에는 서브 쉘이 필요하지 않습니다. 재 지정 은 서브 쉘이 아닌을 사용한 명령 그룹화 만 필요합니다 { … }.

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

( 변수 대체에 대한 큰 따옴표를 잊지 마십시오 .)


모든 프로그래밍 언어가 그렇게 할 수 있다는 것은 재밌습니다. 나는 이미 껍질에 가능한 해결책없이 1 시간 인터넷 검색을 보냈습니다. 나는 실망했다.
Kra에

1
@ToKra 아니요. 프로그래밍 언어로는이 작업을 수행 할 수 없습니다. (거의) 모든 프로그래밍 언어는 서브 루틴 또는 명령 블록 에서 변수 값을 부모로 가져올 수 있으며, 이것이 바로 내 대답에서 설명하는 것과 같습니다 . { … }서브 쉘 대신 명령 그룹화 를 사용하십시오 ( … ).
Gilles 'SO- 악의를 멈춰라'

4

연구원 U & L 사용자 :와 C 스타일의 사용에 대한 내 대답 downvoting하기 전에 main(): 기능을,이 링크를 방문하시기 바랍니다 https://unix.stackexchange.com/a/313561/85039을 스크립트에서 많은 전문가가 사용하는 일반적인 방법을, 주요 기능을한다 사용 해당 영역에서.


Gilles가 지적했듯이 서브 쉘은 환경 외부에서 변수를 사용할 수 없습니다. 그러나이 문제를 다른 각도에서 접근 해 봅시다. 함수로 스크립트를 작성하면 변수를 선언 local할 수 있으며 편집 할 수 있습니다.

bash 4.3 매뉴얼에서 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 번 ​​반복 한 후 볼 수 있듯이 변수가 수정됩니다.


C 프로그래머에게는 직관적이지 않은 행동입니다. 일반적으로 outter의 글로벌 인스턴스를 참조 할 것으로 예상 됩니다 var.
Ruslan

이 답변에는 몇 가지 결함이 있습니다. "$var"콜 아웃에는 필요하지 않습니다 outter. 아무것도하지 않습니다. 또한 local var=0아무것도하지 않습니다. 당신이 언급했듯이 call ouf outter는 덮어 씁니다 var.
Golar Ramblar

@GolarRamblar 나는 "$var"위치 인수로 제거 했다 outter; 공정하게 말하면, 이것은 습관이 아닙니다. 당신은 local var=0 부분으로 정교하게 할 수 있습니까 ?
Sergiy Kolodyazhnyy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.