Skip to main content

10. Variables - Part II

이미 설정된 변수 집합이 있으며, 이러한 변수에는 대부분 값을 할당할 수 없습니다. 이러한 변수에는 스크립트가 실행 중인 환경에 대해 파악하는 데 사용할 수 있는 유용한 정보가 포함될 수 있습니다.

첫 번째로 살펴볼 변수 집합은 $0 ... $9 및 $#입니다. 변수 $0은 호출된 프로그램의 기본 이름입니다. $1 ... $9는 스크립트가 호출된 처음 9개의 추가 매개변수입니다. 변수 $@는 모든 매개변수 $1 .. 뭐든지입니다. 변수 $*는 비슷하지만 공백을 보존하지 않고 따옴표를 사용하지 않으므로 " File with spaces"는 "File" "with" "spaces"가 됩니다. 이는 첫 번째 스크립트에서 살펴본 echo와 유사합니다. 일반적으로 $@을 사용하고 $*은 피하세요. 여기서 $#은 스크립트가 호출된 매개변수 수입니다. 예제 스크립트를 살펴보겠습니다:

#!/bin/sh
echo "I was called with $# parameters"
echo "My name is $0"
echo "My first parameter is $1"
echo "My second parameter is $2"
echo "All parameters are $@"

이 코드를 실행하여 출력을 확인해 보겠습니다:

$ /home/steve/var3.sh
I was called with 0 parameters 
My name is /home/steve/var3.sh 
My first parameter is
My second parameter is
All parameters are
$
$ ./var3.sh hello world earth 
I was called with 3 parameters 
My name is ./var3.sh
My first parameter is hello
My second parameter is world
All parameters are hello world earth

$0의 값은 스크립트가 호출된 방식에 따라 달라집니다. 외부 유틸리티 베이스네임으로 이 문제를 해결할 수 있습니다:

echo "My name is `basename $0`"

$#과 $1 ... $2는 셸에 의해 자동으로 설정됩니다. 아래 스크립트를 보면 shift 명령을 사용하여 9개 이상의 매개변수를 사용할 수 있습니다:

#!/bin/sh
while [ "$#" -gt "0" ]
do
  echo "\$1 is $1"
  shift
done

이 스크립트는 $#이 0이 될 때까지, 즉 목록이 비어 있을 때까지 계속 shift를 사용합니다.

또 다른 특수 변수는 $? 여기에는 마지막 실행 명령의 종료 값이 포함됩니다. 따라서 코드:

#!/bin/sh
/usr/local/bin/my-command
if [ "$?" -ne "0" ]; then
  echo "Sorry, we had a problem there!"
fi

는 모든 것이 정상적으로 진행되면 0 값을 반환하고, 실패하면 0이 아닌 값으로 종료되는 /usr/local/bin/my-command를 실행하려고 시도합니다. 그러면 명령을 호출한 후 $? 값을 확인하여 이 문제를 처리할 수 있습니다. 이렇게 하면 스크립트를 더욱 강력하고 지능적으로 만들 수 있습니다. 제대로 작동하는 애플리케이션은 성공 시 0을 반환해야 합니다. 그래서 따옴표를 붙인 것입니다:

"로마 제국이 멸망한 주요 원인 중 하나는 0이 없었기 때문에 C 프로그램의 성공적인 종료를 알릴 방법이 없었기 때문입니다."
(Robert Firth)

환경에 의해 설정되는 다른 두 가지 주요 변수는 $$ 및 $! 둘 다 프로세스 번호입니다. 변수 $$는 현재 실행 중인 셸의 PID(프로세스 식별자)입니다. 이 변수는 스크립트의 여러 인스턴스가 동시에 실행될 수 있고 모두 고유한 임시 파일이 필요한 경우 유용하게 사용할 수 있는 /tmp/my-script.$$와 같은 임시 파일을 만드는 데 유용할 수 있습니다. ! 변수는 마지막으로 실행된 백그라운드 프로세스의 PID입니다. 이는 프로세스가 작업을 진행하면서 추적하는 데 유용합니다.

또 다른 흥미로운 변수는 IFS입니다. 이것은 내부 필드 구분 기호입니다. 기본값은 SPACE TAB NEWLINE이지만 변경하는 경우 그림과 같이 복사하는 것이 더 쉽습니다:

#!/bin/sh
old_IFS="$IFS"
IFS=:
echo "Please input some data separated by colons ..." 
read x y z
IFS=$old_IFS
echo "x is $x y is $y z is $z"

이 스크립트는 다음과 같이 실행됩니다:

$ ./ifs.sh
Please input some data separated by colons ... 
hello:how are you:today
x is hello y is how are you z is today

다음과 같이 "[hello:how are you:today:my:friend"라고 입력하면 다음과 같이 출력됩니다:

$ ./ifs.sh
Please input some data separated by colons ... 
hello:how are you:today:my:friend
x is hello y is how are you z is today:my:friend

특히 IFS를 다룰 때는 공백, 개행 및 기타 "제어할 수 없는" 문자를 포함할 수 있다는 점을 인식하는 것이 중요합니다. 따라서 큰따옴표로 묶는 것이 좋습니다(예: old_IFS=$IFS 대신 old_IFS="$IFS").