bash 쉘 스크립트

서버관련2011. 4. 22. 13:59HanQ eNFO

1. 위치 매개변수와 명령줄 매개변수

    1) 위치 매개변수

        -> 스크립트 이름 다음에 공백 문자로 구분된 각 단어를 매개변수라 부른다

        -> 명령줄 매개변수는 스크립트 내에서 위치 매개변수로 참고할 수 있으며, 
             $1은 첫번째, $2는 두번째 매개변수를 의미한다

        -> $9 이후 매개변수들은 중괄호를 이용하여 숫자부분을 ${10}처럼 묶어주어야 한다

        -> 변수 $#은 전체 위치 매개변수의 개수를 알아보는데, 
            변수 $*는 전체 위치 매개변수의 내용을 알아보는데 사용한다

        -> 위치 매개변수는 set 명령을 써서 설정(set) 또는 재설정(reset)할 수 있으며, 
             set명령을 사용하면 이전 설정값은 지워진다

        -> 위치 매개변수

         $0           : 현재 쉘 스크립트의 이름                                  
         $#           : 위치 매개변수의 총 개수를 평가한다                        
         $*           : 모든 위치 매개변수를 평가한다                             
         $@           : 큰 따옴표를 사용하였을 때를 제외하고는 $*와 동일한 의미      
         "$*"         : "$1 $2 $3"으로 평가한다                                 
         "$@"         : "$1" "$2" "$3"으로 평가한다                             
         $1 ... ${10} : 사용가능한 위치 매개변수
  
                        
            $ cat test
            #!/bin/bash
            echo "This script is called $0."
            echo "$0 $1 and $2"
            echo "The number of positional parameters is $#"

            $ ./test
            This script is called ./test.
            ./test  and
            The number of positional parameters is 0

            $ ./test aaa
            This script is called ./test.
            ./test aaa and
            The number of positional parameters is 1

            $ ./test aaa bbb
            This script is called ./test.
            ./test aaa and bbb
            The number of positional parameters is 2


    2) set 명령과 위치 매개변수

        -> 위치 매개변수를 재설정하면 기존의 값들은 잃어버리게 된다

        -> 모든 위치 매개변수의 설정을 해제하려면 'set --' 명령을 사용한다

        -> $0는 언제나 스크립트 이름을 가리킨다

            $ cat test
            #!/bin/bash
            echo The name of this script is $0
            echo The arguments are $*
               
                => $*은 모든 위치 매개변수를 의미한다

            set $(date)
            echo The date is $2, $3, $6.


            $ ./test a b c d
            The name of this script is ./test
            The arguments are a b c d
            The date is 11., 21., KST.


            $ cat test
            #!/bin/bash
            name=${1:?"requires an argument"}
            echo Hello $name

                => 특수 변수 변경자인 :?는 $1이 값을 가지고 있는지 검사한다

                => 지정한 값이 없으면 스크립트를 종료하고 메시지를 출력한다


            $ ./test
            ./test: line 2: 1: requires an argument

            $ ./test aaa
            Hello aaa


        -> $*와 $@의 차이

            => $*와 $@의 의미는 큰 따옴표 안에서 사용되는 경우에만 서로 다르다
           
            => 큰 따옴표 안에 $*를 사용하는 경우에는 매개변수들이 단일 문자로 취급된다

            => $@를 큰 따옴표 안에 사용하면 매개변수들은 서로 분리된 문자로 인식된다

                $ set 'aaa bbb' ccc ddd
                $ for i in $*

                > do
                > echo $i
                > done
                aaa
                bbb
                ccc
                ddd

                $ set 'aaa bbb' ccc ddd
                $ for i in "$*"
                > do
                > echo $i
                > done
                aaa bbb ccc ddd

                    > $*이 큰 따옴표 안에 들어있기 때문에 전체 매개변수를 하나의 문자열로 처리한다


                $ set 'aaa bbb' ccc ddd
                $ for i in $@
                > do
                > echo $i
                > done
                aaa
                bbb
                ccc
                ddd

                $ set 'aaa bbb' ccc ddd
                $ for i in "$@"
                > do
                > echo $i
                > done
                aaa bbb
                ccc
                ddd

                    > $@가 큰 따옴표 안에 있으므로 각 위치 매개변수를 개개의 문자열로 처리한다


2. 조건의 표현과 흐름 제어

    1) 종료 상태

        -> 종료 상태는 명령이 성공했는지 실패했는지 검사하는 것이고 다른 하나는 표현식이 참인지 거짓인지
            판별하는 것이다

        -> 종료 상태가 0이면 성공이나 참을 의미한다

        -> 종료 상태가 0이 아니면 실패나 거짓을 의미한다

        -> ? 변수는 가장 마지막으로 실행된 명령의 종료 상태를 보관한다

           
    2) test 내장 명령

        -> 단일 대괄호와 test 명령

            => 표현식의 평가에는 일반적으로 test 명령을 사용한다

            => test 명령은 대괄호 ([ ])로도 표현할 수 있다

            => test 명령이나 대괄호를 사용하여 식을 평가할 때, 쉘은 메타문자를 전개하지 않는다

            => 변수에 값을 저장할 때는 단어 단위로 나뉘어 저장하게 되므로 스페이스를 포함한 문자열은
                따옴표로 묶어준다

        -> 이중 대괄호와 test 명령

            => 배시 2.x 버전 이상에서는 이중 대괄호 ([[ ]])를 사용하여 표현식을 평가할 수 있다

            => 단어를 분리하여 변수에 저장하지 않고 패턴 검색이 가능할 뿐만 아니라, 
                메타문자에 대한 해석도 수행한다

            => 스페이스를 포함하는 문자열에는 반드시 따옴표를 사용하여야하며, 
                스페이스의 포함 여부와 상관없이 정확히 일치하는지의 여부를 검사할 때도 따옴표를 
                사용하여야 한다

            => test 명령에서는 논리연산자 &&(and), ||(or)를 -a, -o 옵션으로 치환하여 사용할 수 있다

        -> test 명령 연산자

      => 문자열 검사                                                              
          [ string1 = string2 ]  : string1은 string2와 같다                     
          [ string1 == string2 ] : string1은 string2와 같다                            
          [ string1 != string2 ] : string1은 string2와 다르다                   
                                   (!= 양족에는 스페이스를 사용하여야 한다 )        
          [ string ]             : string은 널이 아니다                          
          [ -z string ]          : string의 길이가 0 이다                        
          [ -n string ]          : string의 길이가 0이 아니다                    
          [ -l string ]          : string의 길이(문자의 개수)                    

      => 논리 검사                                                                
          [ string1 -a string2 ] : and 연산자                                   
          [ string1 -o string2 ] : or 연산자                                    
          [ ! string1 ]          : not 연산자                                  

      => 논리검사(복합 test 명령)                                                  
          [[ pattern1 && pattern2 ]] : pattern1과 pattern2가 모두 참                
          [[ pattern1 || pattern2 ]] : pattern1과 pattern2 중에 하나가 참            
          [[ ! pattern ]]            : pattern과 같지 않다                          

      => 정수 검사                                                                
          [ int1 -eq int2 ]          : int1은 int2와 같다                           
          [ int1 -ne int2 ]          : int1은 int2와 다르다                         
          [ int1 -gt int2 ]          : int1은 int2보다 크다                         
          [ int1 -ge int2 ]          : int1은 int2보다 크거나 같다                   
          [ int1 -lt int2 ]          : int1은 int2보다 작다                         
          [ int1 -le int2 ]          : int1은 int2보다 작거나 같다                  

      => 파일 검사를 위한 이항 연산자                                               
          [ file1 -nt file2 ]        : file1이 file2보다 새로운 파일이면 참           
          [ file1 -ot file2 ]        : file1이 file2보다 오래된 파일이면 참           
          [ file1 -ef file2 ]        : file1과 file2가 동일한 장치이거나 같은         
                                       inode 번호를 가면 참                    

            $ name=kyoung
            $ grep "$name" /etc/passwd
            kyoung:x:1000:1000:kyoung,,,:/home/kyoung:/bin/bash
            $ echo $?
            0

            $ test $name != kyoung
            $ echo $?
            1

            $ [ $name = kyoung ]
            $ echo $?
            0

            $ [ $name = [Kk]????? ]
            $ echo $?
            1
           
                > test 명령에서는 와일드 카드를 사용할 수 없다 따라서 ?를 일반 문자로 취급한다


        -> let 명령과 이중 괄호로 산술연산 처리

            => 산술식 평가에도 test 명령을 사용할 수 있지만, C언어에서처럼 풍부한 연산자를 사용하고 싶다면
               let 명령의 사용을 권장한다

            => let 명령은 이중 소괄호 ((( )))로 치환하여 사용할 수 있다

            => let 명령 연산자

             -                : 음수                          
             +                : 양수                           
             !                : 논리 부정                      
             ~                : 비트 단위 부정                  
             *                : 곱셈                           
             /                : 나누기                         
             %                : 나머지                         
             +                : 덧셈                          
             -                : 뺄셈     
                     
             bash 2.x 이후 추가된 let 연산자                        
             <<               : 비트 단위 왼쪽 시프트           
             >>               : 비트 단위 오른쪽 시프트          
             <= >= <>         : 비교 연산자                    
             == !=            : 등호 연산자                    
             &                : 비트 단위 and                  
             ^                : 비트 단위 배타적 or             
             |                : 비트 단위 or                   
             &&               : 논리곱(and)                    
             ||               : 논리합(or)                     
             = *= /= %= += -= 
             <<= >>= &= ^= |= : 대입 및 복합 연산자
        


                $ x=2
                $ y=3

                $ (( x > 2 ))
                $ echo $?
                1

                $ (( x < 3 ))
                $ echo $?
                0

                $ (( x == 2 && y == 3 ))
                $ echo $?
                0

                $ (( x > 2 || y < 3 ))
                $ echo $?
                1

    - if 명령
 
        -> if문은 종료 상태 값이 0이면 명령이 성공적으로 수행되었음을 
           의미하고 키워드 then 다음의 문장들이 실행된다 
 
        -> 형식 
 
            if 명령
            then
                명령
                명령
            fi
 
 
            => 숫자 및 문자열에 대해 test 사용 - 구형식
 
                if test 조건식
                then 
                    명령
                fi
 
                또는 
 
                if [ 문자열/수식 ] then
                    명령
                fi
 
         
            => 문자열에 대해 test 사용 - 새형식
 
                if [[ 문자열 조건식 ]] then 
                    명령
                fi
 
             
            => 숫자에 대해 let 사용 - 새형식
 
                if (( 수식 ))
 
             
            $ shopt -s extglob
 
                > shopt 내장 명령이 extglob을 설정하면 확장 메타 문자를 쓸 수 있다 
         
            $ answer="not really"
 
            $ if [[ $answer = [Nn]o? ( way|t really ) ]]
            then
                echo "So sorry."
            fi
 
                > 확장 패턴 검색을 사용한다 
 
                > 이 표현식에 따르면 answer 변수의 값이 no나 No로 시작하고 괄호 안에 
                  있는 표현식이 0번 또는 1번 나오면 전체 표현식은 참이 된다 
 
 
 
        -> exit 명령과 변수      
 
            => exit 명령은 스크립트를 중지시키고 명령줄로 돌아가고자 할 때 사용한다 
 
            $ if (( $# != 2 ))
            then 
                echo "Usage: $0 mdays size " 1>&2
                exit 1
            fi
 
                > 매개변수가 2개가 아니면 오류 메시지를 표준 오류로 출력시키고 스크립트의
                  종료 상태를 1로 반환하고 종료한다
 
 
 
        -> 널 값 검사 
 
            => 변수가 널인지 검사할 때는 널의 표현에 큰 따옴표를 사용하여야한다
               그렇지 않으면 test 명령이 실패한다          
 
            $ if [ "$name" = "" ]
            then
                echo The name variable is null 
            fi
 
                > 변수 name의 값이 널이면 검사 결과는 참이되며 큰 따옴표는 널을 표현하기 위해 
                  사용한다 
 
             
 
    3) if/else 명령
 
        -> if/else 명령은 양자 택일을 표현하는데 사용한다 
 
        -> 형식 
 
            if 명령
            then 
                명령(들)
            else
                명령(들)
            fi
 
             
            $ if grep "$name" /etc/passwd >& /dev/null; then 
                echo Found $name!
            else
                echo "Can't find $name."
                exit 1
            fi
 
 
    4) if/elif/else 명령
 
        -> 다중 택일 표현이다 
 
        -> 형식 
 
            if 명령
            then 
                명령(들)
            elif 명령
            then 
                명령(들)
            elif 명령
            then 
                명령(들)
            else
                명령(들)
            fi
 
 
    5) 파일 검사 
 
        -> 스크립트를 작성하다 보면 특정 파일에 대한 정보가 필요한 경우 사용
 
        -> 파일의 권한, 형식, 기본속성 등을 확인 할 때 사용한다 
 
        -> 파일 검사 연산자 
 
          -b filename : 블럭 파일                                      
          -c filename : 문자 파일                                      
          -d filename : 디렉토리가 존재                                 
          -e filename : 파일이 존재                                     
          -f filename : 파일이 존재하고, 디렉토리가 아님                  
          -G filename : 파일이 존재하고, 유효 그룹 ID의 소유이다           
          -g filename : setGID가 설정되어 있다                          
          -k filename : 스티키 비트가 설정되어 있다                       
          -L filename : 파일이 심볼릭 링크이다                           
          -p filename : 파일이 명명된 파이프 이다                        
          -O filename : 파일이 존재하고, 유효 사용자 ID의 소유이다         
          -r filename : 파일이 읽기 가능하다                             
          -S filename : 파일이 소켓이다                                 
          -s filename : 파일 크기가 0이 아니다                           
          -t fd       : 파일 식별자가 터미널에 열려있다                   
          -u filename : setUID가 설정되어 있다                          
          -w filename : 파일에 쓰기가 가능하다                           
          -x filename : 파일이 실행 가능하다                
 
            if [ -d $file ] 
            then 
                echo "$file is a directory"
 
                    > file이 디렉토리이면 출력 
 
            elif [ -f $file ]
 
                    > file이 디렉토리가 아니면 다시 검사 
            then 
                if [ -r $file -a -w $file -a -x $file ]
                then 
                    echo "You have read, write, and execute \ permission on $file."
                fi
                     
                    > file이 읽기,쓰기,실행 모두 가능하면 출력
 
                else 
                    echo "$file is neither a file nor a directory."
 
                    > 위 내용이 모두 거짓이면 출력
 
            fi         
 
 
    6) null 명령
 
        -> null 명령은 내장 명령으로서 콜론(:)으로 나타낸다 
     
        -> 실제 아무런 작업도 하지 않으며, 단지 종료 상태를 0으로 돌려준다 
 
        -> 주로 if 다음에 어떤 작업도 지정하고 싶지 않을 때 사용한다 
 
        -> then 다음에 문장을 기술하지 않으면 오류가 발생하기 때문에, 무한 반복문을 작성할 때도 
           사용한다 
 
            name=Tom
            if grep "$name" databasefile >& /dev/null
            then
             : 
            else
                echo "$1 not found in databasefile"
                exit 1
            fi
 
                > 콜론(:)은 널 명령으로 종료 상태 값을 0으로 되돌리기 외에 아무 일도 
                  하지 않는다 
 
 
            $ DATAFILE=
            $ : ${DATAFILE:=$HOME/db/datafile}
            $ echo $DATAFILE
            /home/jody/ellie/db/datafile
 
                > 콜론(:) 명령은 아무것도 하지 않는 명령이다 
 
                > 변경자 :=에 의해 널인 변수 값이 지정한 값으로 치환된다 
 
                > 변경된 값은 DATAFILE에 영구적으로 설정된다 
 
 
    7) case 명령
 
        -> 다중 분기 명령으로 if/elif 대신 사용한다 
 
        -> case문의 변수가 value1, value2, ... 중의 하나와 일치하면 그 값 이후부터 이중 세미콜론(;;)이 
           나올때까지의 명령들이 실행된다
 
        -> 수행 후에는 esac 다음으로 프로그램의 제어가 옮겨 진다 
 
        -> case 변수와 대응되는 것이 없으면, *) 기호 다음에서 부터 esac 사이의 문장들을 수행한다 
 
        -> *)의 역할은 if/else 조건문에서 else 문장과 동일하다 
 
        -> case 변수의 값에는 와일드 카드나 |(OR연산자)를 사용할 수 있다 
 
        -> 형식
 
            case 변수 in 
            value1)
                명령(들)
                ;;
            value2)
                명령(들)
                ;;
            *)
            명령(들)
                ;;
            esac grep 단어 파일명 파일명 ...
 
 
            $ cat test
 
            echo -n "Choose a foreground color for your xterm window: "
            read color
             
            case "$color" in 
            [Bb]l??)
                xterm -fg blue -fn terminal &
                ;;
             
            [Gg]ree*)
                xterm -fg darkgreen -fn terminal &
                ;;
             
            red | orange)
                xterm -fg $color -fn terminal & 
                ;;
 
            *)
                xterm -fn terminal 
                ;;
 
            esac
 
            echo "Out of case command"
 
         
        -> here 문서와 case 명령을 이용한 메뉴 구성
 
            => here 문서와 case 명령은 함께 사용되는 경우가 잦다 
 
            => here 문서는 화면에 출력될 메뉴를 구성하는 데 사용하며, case 명령은 
               사용자의 선택을 검사하여 적절한 메뉴 항목을 수행시킨다 
 
 
            $ cat test 
 
            echo "Select a terminal type: "
            cat <<- ENDIT
                1) unix
                2) xterm
                3) sun
            ENDIT
 
            read choice
             
            case "$choice" in 
            1)     TERM=unix
                export TERM
                ;;
             
            2)     TERM=xterm
                export TERM
                ;; 
 
            3)     TERM=sun 
                export TERM
                ;;
            esac
            echo "TERM is $TERM."

출처:  
http://blog.blueweb.co.kr/186

'서버관련' 카테고리의 다른 글

[펌]Apache 403 Forbidden error 해결 방법  (4) 2011.12.08
AWK 명령어  (0) 2011.04.24
VI편집기(VIM)  (1) 2011.04.22
bash 쉘 스크립트 - 반복명령, 함수  (0) 2011.04.22
bash 쉘 스크립트  (0) 2011.04.22
블로그 주인 사진AuthoreNFO
자주 잊어먹는것들을 기록해 놓을려고합니다.^^