Variables

변수 이름은 알파벳 (대, 소문자), 숫자, _ 로 만들 수 있으며 이름의 첫 문자로 숫자가 올 수 없습니다. 변수이름을 대문자로 사용할때는 shell 환경변수와 중복되지 않도록 주의해야 합니다. 생성한 변수는 subshell 이나 source 한 스크립트 내에서는 별다른 설정 없이 사용할 수 있으나 child process 에서도 사용하려면 export 해야 합니다.

# '.' or '-' 문자는 변수 이름을 구성하는데 사용되지 않으므로 다음과 같이 사용할 수 있습니다.
# 결과적으로 FILE_PREFIX 변수값은 'myfile.split' or 'myfile-split' 이 됩니다.

ORIGINAL_FILE=myfile

FILE_PREFIX=$ORIGINAL_FILE.split   # '.' 사용
FILE_PREFIX=$ORIGINAL_FILE-split   # '-' 사용

현재 shell 에 정의된 모든 변수명 보기

$ compgen -A variable

# 현재 shell 에 특정 변수가 설정되어 있는지 간단히 확인하는 방법
# 가령 대문자 B 로 시작하는 변수를 조회하려면
$ $B[tab]

정의된 변수 삭제하기

$ unset -v 변수명

Variable states

Shell 에서는 변수의 상태를 3 가지로 구분해볼 수 있습니다.

1 . 변수가 존재하지 않는 상태 또는 unset 상태

변수가 존재하지 않는 상태란 변수에 값을 ( null 값 포함 ) 한번도 대입한 적이 없는 상태를 말합니다. 그러므로 값을 할당하지 않고 declare AA or local AA 와 같이 선언만 한 경우도 해당됩니다. 이미 사용했던 변수도 unset 명령을 사용하면 이 상태로 됩니다.

2 . null 값인 상태

다음과 같은 경우 변수가 존재하고 null 값을 갖고있는 상태가 됩니다.

AA=  AA=""  AA=''
3 . null 이외의 값을 가지고 있는상태

다음과 같은 경우 변수가 존재하고 무엇이든 값을 가지고 있는 상태입니다.

AA=" "  AA="hello"  AA=123

값을 구분하기

3번 무엇이든 값을 가지고 있는 상태와 그렇지 않은 상태 ( 1, 2번 ) 은 다음과 같이 구분할 수 있습니다.

# $var 가 1, 2 번 상태일 때 참
if [ -z "$var" ]; then ...  

# $var 가 3 번 상태일 때 참
if [ -n "$var" ]; then ...

변수가 존재하지 않는 1번 unset 상태와 2번 null 값 상태는 다음 명령으로 구분할 수 있습니다. unset 상태일 경우는 1 을 그외는 0 을 리턴합니다.

$ [ -v asdfgh ]; echo $?   # 현재 asdfgh 변수는 존재하지 않는 상태 ( 1번 상태 )
1

$ asdfgh=""                # 변수는 존재하나 null 값인 상태 ( 2번 상태 )
$ [ -v asdfgh ]; echo $?
0

$ asdfgh=123               # 3번 상태
$ [ -v asdfgh ]; echo $?
0

$ unset -v asdfgh          # unset 했으므로 다시 1번 상태가 됩니다.
$ [ -v asdfgh ]; echo $?
1

shell 옵션 중에는 set -u ( nounset ) 이 있는데요. 이 옵션을 설정하면 1번 존재하지 않는 변수 사용시 오류를 반환하고 스크립트를 종료합니다. 테스트를 위해 subshell 를 사용함으로써 종료시 subshell 만 종료되게 할 수 있고 옵션 설정 또한 subshell 에 국한할 수 있습니다.

$ ( set -u; echo 111 $asdfgh; echo end... )     # 현재 $asdfgh 변수는 존재하지 않는 상태
bash: asdfgh: unbound variable

$ echo $?           # 오류를 반환하고 종료하므로 마지막 echo end... 는 실행되지 않는다.
1
............................................

$ ( set -u; $asdfgh && echo 111; echo end... )
bash: asdfgh: unbound variable

$ echo $?
1
...........................................

$ asdfgh=""         # 2번 상태는 정상적으로 실행
$ ( set -u; echo 111 $asdfgh; echo end... )
111
end...

sh 에서는 -v 옵션을 사용할 수 없는데요. 하지만 set -u ( nounset ) 옵션을 활용하면 동일한 테스트를 할 수 있습니다.

# ':' 명령의 인수로 변수를 사용함으로써 변수의 존재 여부를 테스트할 수 있습니다.

sh$ ( set -u; : $asdfgh ) 2> /dev/null; echo $?  # 현재 $asdfgh 변수는 존재하지 않는 상태
2

sh$ asdfgh=""
sh$ ( set -u; : $asdfgh ) 2> /dev/null; echo $?
0

sh$ asdfgh="123"
sh$ ( set -u; : $asdfgh ) 2> /dev/null; echo $?
0

sh$ unset -v asdfgh
sh$ ( set -u; : $asdfgh ) 2> /dev/null; echo $?
2

&& , || 를 이용한 변수값 설정

| 파이프와 달리 && , || 에 연결된 명령은 현재 shell 에서 실행되므로 변수값을 설정하는데 사용할 수 있습니다.

# 명령이 성공하면 myvar 변수값을 100 으로 설정
$ command ... && myvar=100

# 명령이 실패하면 myvar 변수값을 100 으로 설정
$ command ... || myvar=100

# 명령이 성공하면 100 으로 설정, 실패하면 200 으로 설정
$ command ... && myvar=100 || myvar=200

$ echo $myvar 
100
-----------------------------------------------------

# '|' 파이프에 연결된 명령은 subshell 에서 실행되므로 
# 설정한 변수값을 이후의 명령에서 사용할 수 없습니다.
$ command ... | myvar=100

$ echo $myvar
$                # 값이 표시되지 않는다.

변수값으로 NUL 문자를 저장할 수 없다.

NUL 문자( \0 )는 변수의 값으로 저장할 수 없습니다. 하지만 pipe 로 전달하거나 file 로 저장할 수는 있습니다.

$ var=$(echo -en "AA\x09\x0aBB")
$ echo -n "$var" | od -a
0000000   A   A  ht  nl   B   B     # tab, newline 같은 문자들은 정상적으로 저장된다.
0000006

$ var=$(echo -en "AA\x00\x00BB")    # \x00 대신 \0 로 해도됨
$ echo -n "$var" | od -a
0000000   A   A   B   B             # null 문자는 모두 제거되었다.
0000004

--------------------------------

# enter 후에 마우스를 움직이면 NUL 문자값(00) 이 pipe 를 통해 전달되는 것을 볼 수 있습니다.
$ sudo cat /dev/input/mice | od -tx1
0000000 18 fe 09 18 fd 07 18 fc 09 18 fe 08 18 fe 06 18
0000020 ff 05 18 ff 04 08 00 03 08 00 03 08 00 02 08 00
0000040 02 08 01 01 08 01 01 08 01 01 08 01 00 08 01 00
0000060 28 01 ff 28 01 ff 28 00 fe 28 00 ff 28 00 fe 28
....

NUL 문자는 ascii table 상에 \x00 값을 가지고 있는 A (\x41), B (\x42) 와 같은 값입니다. 반면에 본문에 사용된 null 값은 empty 값을 의미합니다.