Passion/Programming

Shell 프로그래밍

sunshout 2008. 12. 12. 15:00


간단한 프로그래밍이나 프로그램 설치시에 많은 Shell 들이 사용된다.

이러한 기본적인 Shell의 동작원리를 파악하는 것은 명량 코딩에 도움을 준다.
여기에서는 간단한 Shell에 대한 원리를 이해하고 정리하려고 한다..

참고:
http://kldp.org/KoreanDoc/Shell_Programming-KLDP

1. 변수
   - 변수를 정의할 때는 변수명 앞에 $를 붙이고, 값을 할당할 때는 그냥 변수명만을 써준다.
   - 변수는 타입을 가지고 있지 않다.

기본 환경 변수들 (Language : text)
최초 실행시 적용되는 변수
---------------------------
$0 - 실행된 쉘 스크립트 이름
$# - 스크립트에 넘겨진 인자의 갯수
$$ - 쉘 스크립트의 프로세스 ID

Parameter로 받은 변수들
---------------------------
$1~ $nnn  : 넘겨진 인자들
$*        : 스크립트에 전달된 인자들을 모아놓은 문자열. 하나의 변수에 저장되며 IFS 환경변수의 첫번째 문자로 구분된다.
$@        : $*과 같다. 다만 구분자가 IFS변수의 영향을 받지 않는다.
 

1.1 set을 이용한 매개 변수 할당
    쉘 내부의 인자($#)에 대해서 설정을 해준다.

set 예제 (Language : text)
echo $#
set $(ls)
echo $#

결과
0
1

확인
#ls
test.sh

1.2 Shell debug
  쉘을 실행하면서 어떤 동작이 진행되고 있는지를 파악하기 위해서는
  set -x 를 써주면 된다.
  debugging 모드를 off하려면 set +x 를 하면 된다.

1.3 매개 변수 확장
  형식 %는 뒤를 의미하고 #은 앞을 위미한다고 보면 될듯

  ${parm:-default} : parm이 존재하지 않으면 default로 대체된다.
  ${#parm}          : parm의 길이를 참조한다.(가져온다)
  ${parm%word}      : 끝에서부터 word와 일치하는 parm의 최소부분(첫번째 일치) 을
                      제거하고 나머지를 반환한다.
  ${parm%%word}     : 끝에서부터 word와 일치하는 parm의 최대부분(마지막 일치) 을
                      제거하고 나머지를 반환한다.
  ${parm#word}      : 처음부터 word와 맞는 parm의 최소부분(첫번째 일치)을 제거하
                      고 나머지 부분을 반환한다.
  ${parm##word}     : 처음부터 word와 맞는 parm의 최대부분(마지막 일치)을 제거하
                      고 나머지를 반환한다.

매개변수 확장 예제 (Language : text)
cur_dir=$(pwd)
a=${#cur_dir}
echo "Current dir:$cur_dir"
echo "length: $a"

b=${cur_dir%/*}       #뒤에서부터 /* 를 삭제하고 앞에거를 리턴
echo $b

c=${cur_dir##*/}      #앞에서부터 */를 찾아서 나머지를 리턴
echo $c

실행결과
Current dir:/home/vrouter/project/shell
length: 27
/home/vrouter/project
shell
 





2. 명령어 실행 후 변수에 할당
   명령어 실행은 두가지 방법으로 가능하다.
   첫번째는 `` 사이에 해당 명령어를 넣는 것이다.
   다른 방법은 $() 사이에 명령어를 넣는 것이다.
   이 때 주의해야 할 부분은 변수에 할당이기 때문에 변수명 앞에는 $를 붙이지 않는다.

명령어 실행 후 변수에 할당 (Language : text)
hw1=`uname -a'
hw2=$(uname -a)

echo $hw1
echo $hw2

3.1 Case 문
  ※ 패턴에는 * 문자, 즉 와일드카드를 사용할 수 있다.
  형식 :
      case 변수 in
        패턴 [ | 패턴 ] ... ) 문장 ;;
        패턴 [ | 패턴 ] ... ) 문장 ;;
        ....
        * ) 문장 ;;
      esac

 

case 예제 (OS 버전 체크) (Language : text)
#!/bin/sh

system=$(uname)

case $system in
        *BSD)   echo "BSD variant : $system" ;;
        Linux)  echo "Linux" ;;
        *nux)   echo "Unix variant : $system" ;;
esac


 


3.2 Test
   test 명령의 조건은 다음과 같이 세 부류로 나누어진다.

  문자열비교
    [ string ]             : string이 빈 문자열이 아니라면 참
    [ string1 = string2 ]  : 두 문자열이 같다면 참
    [ string1 != string2 ] : 두 문자열이 다르면 참
    [ -n string ]          : 문자열이 null(빈 문자열) 이 아니라면 참
    [ -z string ]          : 문자열이 null(빈 문자열) 이라면 참

  산술비교
    [ expr1 -eq expr2 ] : 두 표현식 값이 같다면 참 ( EQual )
    [ expr1 -ne expr2 ] : 두 표현식 갑이 같지 않다면 참 ( Not Equal )
    [ expr1 -gt expr2 ] : expr1 > expr2 이면 참 ( Greater Then )
    [ expr1 -ge expr2 ] : expr1 >= expr2 이면 참 ( Greater Equal )
    [ expr1 -lt expr2 ] : expr1 < expr2 이면 참 ( Less Then )
    [ expr1 -le expr2 ] : expr1 <= expr2 이면 참 ( Less Equal )
    [ ! expr ]          : expr 이 참이면 거짓, 거짓이면 참
    [ expr1 -a expr2 ]  : expr1 AND expr2 의 결과 ( 둘다 참이면 참 )
    [ expr1 -o expr2 ]  : expr1 OR expr2 의 결과 ( 둘중 하나만 참이면 참 )

  파일조건

    [ -b FILE ]           : FILE 이 블럭 디바이스 이면 참
    [ -c FILE ]           : FILE 이 문자 디바이스 이면 참.
    [ -d FILE ]           : FILE 이 디렉토리이면 참
    [ -e FILE ]           : FILE 이 존재하면 참
    [ -f FILE ]           : FILE 이 존재하고 정규파일이면 참
    [ -g FILE ]           : FILE 이 set-group-id 파일이면 참
    [ -h FILE ]           : FILE 이 심볼릭 링크이면 참
    [ -L FILE ]           : FILE 이 심볼릭 링크이면 참
    [ -k FILE ]           : FILE 이 Sticky bit 가 셋팅되어 있으면 참
    [ -p FILE ]           : True if file is a named pipe.
    [ -r FILE ]           : 현재 사용자가 읽을 수 있는 파일이면 참
    [ -s FILE ]           : 파일이 비어있지 않으면 참
    [ -S FILE ]           : 소켓 디바이스이면 참
    [ -t FD   ]           : FD 가 열려진 터미널이면 참
    [ -u FILE ]           : FILE 이 set-user-id 파일이면 참
    [ -w FILE ]           : 현재 사용자가 쓸 수 있는 파일(writable file) 이면 참
    [ -x FILE ]           : 현재사용자가 실행할 수 있는 파일(Executable file) 이면 참
    [ -O FILE ]           : FILE 의 소유자가 현재 사용자이면 참
    [ -G FILE ]           : FILE 의 그룹이 현재 사용자의 그룹과 같으면 참
    [ FILE1 -nt FILE2 ]   : FILE1이 FILE2 보다 새로운 파일이면 ( 최근파일이면 ) 참
    [ FILE1 -ot FILE2 ]   : FILE1이 FILE2 보다 오래된 파일이면 참
    [ FILE1 -ef FILE2 ]   : FILE1 이 FILE2의 하드링크 파일이면 참

3. 함수
    함수는 쉘안에 또다른 하나의 쉘이 실행되는 것으로 보면 된다.
    그래서 쉘이 가지고 있는 기본 변수들을 함수내부에서 또 가지게 된다.

func 예제 (Language : text)
nestfunc()
{
        echo $0
        echo $#
        echo $$
        echo $1
}

echo $0
echo $#
echo $$
echo $1

nestfunc abc

결과 (#./test.sh)
./test.sh   # 실행 쉘 이름 $0
1      # 넘겨진 파라매터 갯수
24284       # 프로세스 번호
test.sh     # $1
./test.sh   # nestfunc 함수안에서 실행 쉘 이름
1           # 넘겨진 파라메터 갯수
24284       # 프로세스 번호
abc         # 파라메터 $1 (abc 임에 유의)