5.4. 특수한 변수 타입

지역 변수

지역 변수는 코드 블럭이나 함수에서만 나타납니다(함수에서의 지역 변수 참고).

환경 변수

쉘의 동작과 사용자 인터페이스에 영향을 미치는 변수

참고: 아주 일반적인 상황에서는 각 프로세스는 자신이 참조할 정보들을 담고 있는 변수들의 그룹인 "환경"이란 것을 갖고 있습니다. 이런 관점에서 보면, 쉘도 다른 프로세스들과 다를 바 없습니다.

쉘은 자신이 시작될 때마다 자신의 환경 변수에 대응하는 쉘 변수를 만들어 냅니다. 쉘 변수를 업데이트하거나 새롭게 추가하면 쉘은 자신의 환경 변수를 업데이트 시키고 쉘의 모든 자식 프로세스(쉘에서 실행시킨 명령어들)는 그 환경을 물려 받습니다.

경고

환경용으로 할당된 공간은 제한되어 있습니다. 환경 변수를 너무 많이 만들거나 한 환경 변수가 공간을 지나치게 많이 사용한다면 문제가 생길 수 있습니다.

bash$ eval "`seq 10000 | sed -e 's/.*/export var&=ZZZZZZZZZZZZZZ/'`"

bash$ du
bash: /usr/bin/du: Argument list too long
	          

(명확한 설명을 해 주고 위의 예제를 제공해준 S. C. 에게 감사)

만약에 스크립트가 환경 변수를 세트하면 그 변수는 "export"되어야 합니다. 즉, 그 스크립트에 해당하는 환경으로 보고되어야 한다는 뜻입니다. export 명령어가 이 일을 해 줍니다.

참고: 스크립트는 변수를 오직 자신의 자식 프로세스에게만 export 할 수 있습니다. 즉, 자신이 만들어낸 명령어나 프로세스들만 적용을 받습니다. 명령어줄에서 실행된 스크립트는 특정 변수를 명령어줄 환경으로 거꾸로 export 할 수 없습니다. 자식 프로세스는 자신을 만들어낸 부모 프로세스에게 특정 변수를 거꾸로 export 할 수 없습니다.

---

위치 매개변수(positional parameter)

명령어줄에서 스크립트로 넘어온 인자들로 $0, $1, $2, $3... 이런식으로 표현되는데 $0 은 스크립트의 이름 그 자체를 나타내고 $1 은 첫번째 인자를, $2 는 두번째를, $3 은 세번째를 나타내는 식입니다. [1] $9 다음의 인자는 ${10}, ${11}, ${12} 처럼 중괄호로 묶어줘야 합니다.

예 5-5. 위치 매개변수

#!/bin/bash

# 최소한 10 개의 매개변수를 줘서 이 스크립트를 실행시키세요. 예를 들면,
# ./scriptname 1 2 3 4 5 6 7 8 9 10

echo

echo "스크립트 이름은 \"$0\"."
# 현재 디렉토리를 나타내는 ./ 가 추가되어 있죠.
echo "스크립트 이름은 \"`basename $0`\"."
# 경로명을 떼어 냅니다('basename' 참고).

echo

if [ -n "$1" ]              # 테스트 할 변수를 쿼우트 해줬습니다.
then
 echo "첫번째 매개변수는 $1"  # # 을 이스케이프 시키기 위해서 쿼우트를 해 줘야 됩니다.
fi 

if [ -n "$2" ]
then
 echo "두번째 매개변수는 $2"
fi 

if [ -n "$3" ]
then
 echo "세번째 매개변수는 $3"
fi 

# ...

if [ -n "${10}" ]  # $9 보다 큰 매개변수는 {중괄호}로 감싸야 됩니다.
then
 echo "열번째 매개변수는 ${10}"
fi 

echo

exit 0

어떤 스크립트들은 자신이 불린 이름에 따라 다르게 동작할 수도 있습니다. 이런 식의 동작을 원한다면 스크립트 안에서 자기가 어떻게 불렸는지를 나타내는 $0을 확인하면 됩니다. 스크립트가 어떤 이름으로 불리든지 간에 $0은 그 이름을 정확하게 심볼릭 링크하고 있기 때문입니다.

작은 정보: 명령어줄 매개변수를 예상하고 있는 스크립트가 매개변수 없이 불린다면 널 값이 할당되어 원치 않는 결과를 가져옵니다. 이런 상황을 피하는 한 가지 방법은 위치 매개변수를 변수에 할당하는 문장에서 양쪽에 똑같은 아무 문자나 붙이면 됩니다.

variable1_=$1_
# 이렇게 해주면 위치 매개 변수가 비어있더라도 에러를 막아줍니다.

critical_argument01=$variable1_

# 실제로 변수를 쓸 곳에서 다음처럼 해주면 에러 방지용 문자가 잘려 나갑니다.
variable1=${variable1_/_/}   # $variable1_ 이 "_"로 시작할 때만 부효과(Side effects)가 있습니다.
# 9장에서 논의할 매개변수 치환중의 한 가지 방법을 써서 변경 패턴을 삭제해 줍니다.

#  좀 더 확실한 방법은 원하는 위치 매개변수가 넘어 왔는지 테스트를 해 보는 것입니다.
if [ -z $1 ]
then
  exit $POS_PARAMS_MISSING
fi  

---

예 5-6. wh, whois 도메인 네임 룩업

#!/bin/bash

# ripe.net, cw.net, radb.net 중 하나의 서버에 대해서 
# 'whois domain-name' 룩업을 실행

# 이 스크립트 이름을 'wh' 라고 해서 /usr/local/bin 에 넣어두세요.

# 그리고 다음처럼 심볼릭 링크를 거세요.
# ln -s /usr/local/bin/wh /usr/local/bin/wh-ripe
# ln -s /usr/local/bin/wh /usr/local/bin/wh-cw
# ln -s /usr/local/bin/wh /usr/local/bin/wh-radb


if [ -z "$1" ]
then
  echo "사용법: `basename $0` [domain-name]"
  exit 65
fi

case `basename $0` in
# 스크립트 이름을 확인해서 해당 서버를 부릅니다.
    "wh"     ) whois $1@whois.ripe.net;;
    "wh-ripe") whois $1@whois.ripe.net;;
    "wh-radb") whois $1@whois.radb.net;;
    "wh-cw"  ) whois $1@whois.cw.net;;
    *        ) echo "사용법: `basename $0` [domain-name]";;
esac 

exit 0

---

shift 명령어는 위치 매개변수를 왼쪽으로 한 단계씩 이동시킵니다.

$1 <--- $2, $2 <--- $3, $3 <--- $4, 등등.

원래의 $1 은 없어지지만 $0 은 바뀌지 않습니다. 위치 매개변수가 많이 필요하다면 {중괄호} 표기법으로 가능하지만(예 5-5 참고), shift 를 써서 예전 10개를 쓸 수 있습니다.

예 5-7. shift 쓰기

#!/bin/bash
# 'shift' 로 모든 위치 매개변수를 처리하기.

#  이 스크립트의 이름을 shft 등의 이름으로 바꾸고
#+ ./shft a b c def 23 skidoo
#+ 같은 식으로 몇 개의 인자를 넘겨서 불러 보세요.

until [ -z "$1" ]  # 모든 매개변수를 다 쓸 때까지...
do
  echo -n "$1 "
  shift
done

echo   # 여분의 한 줄.

exit 0

주석

[1]

관습적으로, 스크립트를 호출하는 프로세스는 $0 매개변수를, 호출하는 스크립트의 이름으로 세트합니다. execv 맨페이지를 참고하세요.