새소식

서버관련

bash 쉘 스크립트 - 반복명령, 함수

  • -
SMALL

1. 반복 명령

 1) for 명령

  - for 반복문을 사용하면, 일련의 파일이나 사용자에 대해 동일한 명령들을 반복하여 
    실행시킬 수 있다

  - for 명령 다음에는 사용자 정의 변수가 나오고, 이어서 키워드 in과 단어를 나열한다

  - 일단 변수에 단어가 대입되면 반복문의 본문에 해당하는 do와 done 사이의 명령들이 실행된다

  - 형식

   for 변수 in 단어목록
   do 
    명령(들)
   done


   $ cat mylist 
   aaa
   bbb
   ccc

   $ cat test
   
   for person in $(cat mylist)
  
    > 명령 치환을 수행하면 파일 mylist의 내용이 단어 목록이 된다

    > 반복문이 처음 수행될 때, 변수 person에는 aaa가 저장되며 다음으로 bbb가 저장된다

   do 
    mail $person < letter
    echo $person was sent a letter.
   done
   echo "The letter has been sent."


 2) 단어 목록에서의 $*와 $@ 변수

  - $*는 하나의 문자열로 취급하고, $@는 단어별로 다른 문자열로 취급한다

   $ cat test

   for name in $*
   do 
    echo Hi $name 
   done

    > $*와 $@는 모든 위치 매개변수들의 값으로 전개된다

   $ ./test aaa bbb ccc
   Hi aaa
   Hi bbb
   Hi ccc


   $ cat test1

   for file
   do 
    if [ -f $file -a ! -x $file ]
    then 
     chmod +x $file
     echo $file now has execute permission
    fi
   done

   $ ./test1 *

    > for 문에 단어 목록을 따로 지정하지 않으면 반복문은 위치 매개변수들을 차례로 처리한다

    > for file in $*와 같은 의미이다


 3) while 명령

  - while 명령은 다음에 따라오는 명령을 평가해서, 종료 상태가 0이면 반복문 본문(do와 done사이)의 
     명령들을 수행시킨다

  - 키워드 done에 다다르면, 프로그램의 제어는 다시 반복문의 시작부분으로 옮겨져서 명령의 
     종료상태를 다시 검사한다

  - while 문에 의해 명령의 종료 상태가 0이 아닌 값으로 바뀔 때까지 반복문이 계속되며, 
     종료 상태가 0이 아닌 값인 경우에는 프로그램의 제어 done 다음으로 옮겨져서 계속 실행된다

  - 형식

   while 명령
   do
    명령(들)
   done

   
   $ cat test

   num=0
   while (( $num < 10 ))

    > let 명령은 수식을 평가하여, 종료 상태가 0이면 조건을 참으로 간주한다

   do 
    echo -n "$num "
    let num+=1
   done
   echo -e "\nAfter loop exits, continue running here"

   $ ./test
   0 1 2 3 4 5 6 7 8 9
   After loop exits, continue running here  


 4) until 명령

  - until 명령은 while 명령과 유사하게 사용된다 
  
  - 하지만 until 다음에 나오는 명령이 실패해야 반복문이 실행된다는 점이 다르다

  - 명령의 종료 상태가 0이 아닌 경우에 반복문이 수행된다

  - 형식

   until 명령
   do
    명령(들)
   done


 5) select 명령과 메뉴

  - 배시 쉘에서는 메뉴 생성을 위해 select라는 새로운 반복문을 제공한다

  - 숫자(일련번호)를 선택 항목으로 사용하는 메뉴를 표준 오류로 출력하면
    프롬프트 PS3을 이용해 사용자의 입력을 기다린다

  - PS3의 기본값은 #?이다 
  
  - 사용자는 메뉴 항목에 나타나는 숫자들 중 하나를 선택하여야한다

  - 사용자가 입력한 값은 배시 쉘의 내장 변수인 REPLY에 저장되며, 저장된 숫자는 선택항목의
    결정에 사용한다 
   
  - 변수 LINES와 COLUMNS는 메뉴 항목을 표시할 때, 출력 모양을 설정하기 위해서 사용한다

  - 메뉴가 표준 오류로 출력될 때는 각 항목 앞에 일련 번호와 닫는 기호())가 붙는다

  - PS3 프롬프트는 메뉴의 맨 아래에 출력된다

  - select는 반복문 명령이므로 break 명령을 사용하여 반복문을 빠져나가거나, exit 명령을 사용하여 
    스크립트 전체를 종료할 수 있다

  - 형식

   select var in wordlist
   do
    명령(들)
   done


   $ cat test 
   PS3="Select a program to execute: " 
   select program in 'ls -F' pwd date
   do 
    $program 
   done

   $ ./test
   1) ls -f 
   2) pwd
   3) date
   select a program to execute: 2
   /home/ellie

    > PS3 변수에 메뉴 목록의 맨 아래에 표시할 프롬프트를 지정한다

    > 프롬프트를 출력한 후에는 사용자의 입력을 기다리며, 이 프롬프트의 기본값은 $#이다

    > select 반복문은 program 이라는 변수와 세개의 단어 목록으로 구성된다

    > 메뉴 항목으로는 어떤 단어든지 사용할 수 있다


 6) 반복문 제어 명령  

  - 특별한 상황이 발생하면, 반복문을 탈출하거나, 반복문의 시작 부분으로 되돌아가야 하는 경우에 사용한다

  - shift 명령

   -> shift 명령은 매개변수 목록의 순서에서, 지정한 횟수만큼 왼쪽으로 이동 시킨다 
   
   -> 매개 변수를 지정하지 않고 shift 명령을 사용한 경우에는 매개변수 목록의 자리를 
      왼쪽으로 한번만 이동시키며 이동되면 영구히 제거 된다

   -> 형식

    shift [n]


    $ cat test

    set aaa bbb ccc ddd
   
    shift

    echo $*

    shift 2

    echo $*

    
    $ ./test

    bbb ccc ddd
  
    ddd


  - break

   -> 내장 명령 break는 반복문을 즉시 탈출하고자 하는 경우에 사용한다 
      (프로그램은 계속진행되며 프로그램을 종료에는 exit 명령을 사용한다)

   -> break 명령이 실행되면 프로그램의 제어는 곧 바로 done 다음으로 이동한다

   -> 여러 반복문이 중첩되어 있을 때는 break를 사용한 반복문에서만 빠져나온다

   -> 중첩 반복문 구조에서 특정 반복문을 빠져 나오고자 할 때는 break 명령에 
      탈출하고자 하는 외부 반복문을 지정하기 위해 정수 매개 변수를 사용할 수 있다

   -> break는 무한 반복문의 탈출에 유용하게 사용할 수 있다

   -> 형식

    break [n]


    $ cat test

    while true; do 
     
     echo Are you ready to move on\?
     read answer

     if [[ "$answer" == [Yy] ]]
     then

      break               ------------------+
                                            |
     else                                   |
                                            |
      .... commands ....                    |
                                            |
     fi                                     |
                                            |
    done                                    |
                                            |
    print "Here we are"   <-----------------+


  - continue 명령

   -> continue 명령은 지정한 조건이 참이면 제어를 반복문의 시작 부분으로 되돌린다

   -> continue 아래의 명령들은 모두 무시하게되며, 중첩된 반복문의 경우, continue 명령은
        제어를 가장 아래쪽의 반복문으로 넘겨준다

   -> 형식

    continue [n]


    $ cat test

    for name in $(cat mail_list)   <-----------+
    do                                         |
     if [[ $name == richard ]] ; then          |
      continue                     ------------+
     else
      mail $name < memo
     fi
    done


  - 중첩 반복문의 제어

   -> 중첩 반복문을 사용하는 경우, break나 continue 명령들에 정수 매개변수를 주면 반복문들 
      사이의 이동이 가능하다


    $ cat test

    for month in Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec <-------+
                                                                         |
    do                                                                   |
                                                                         |
     for week in 1 2 3 4         <----------------------------------+    |
                                                                    |    |
     do                                                             |    |
                                                                    |    |
      echo -n "Processing the month of $month. OK? "                |    |
                                                                    |    |
      read ans                                                      |    |
                                                                    |    |
      if [ "$ans" = n -o -z "$ans" ]                                |    |
                                                                    |    |
      then                                                          |    |
                                                                    |    |
       continue 2                       ----------------------------|----+ 
                                                                    |
      else                                                          |
                                                                    |
       echo -n "Process week $week of $month? "                     |
                                                                    |
       read ans                                                     |
       if [ "$ans" = n -o -z "$ans" ]                               |
                                                                    |
       then                                                         |
                                                                    |
       continue                        -----------------------------+

       else

       echo "Now processing week $week of $month. "

       sleep 1

       echo "Done processing..."

       fi

      fi
   
     done

    done


  - I/O 리다이렉션과 자식 쉘

   -> 파이프(pipe)나 리다이렉션을 이용하면 파일에서 반복문으로 입력을 전환할 수 있다

   -> 같은 방법으로 출력 역시 반복문에서 파일로 지정할 수 있다

   -> 입출력(I/O) 리다이렉션이나 파이프를 처리하기 위해서는 자식 쉘을 실행시켜야 한다

   -> 반복문 내에서 정의한 변수들은 스크립트의 나머지 부분을 참조할 수 없다

   -> 반복문의 출력을 유닉스/리눅스 명령으로 파이프하기

       > 출력은 파이프를 이용하여 다른 명령의 입력으로 사용될수 있으며, 리다이렉션을 이용해 
          파일로 보낼 수도 있다

    $ cat test

    for i in 7 9 2 3 4 5 
    do 
     echo $i
    done | sort -n

     >> 결과는 sort -n에게 넘겨져 정렬된다


  - 백그라운드에서 반복문 사용

   $ cat test

   for person in aaa bbb ccc ddd

   do 
   
    mail $person < memo

   done &

    > 키워드 done 다음의 &는 반복문을 백그라운드에서 처리하도록 한다

    > 반복문이 실행되는 동안에도 프로그램은 계속 진행된다


  - IFS 와 반복문

   -> 쉘의 내부 필드 구분자(IFS)는 스페이스, 탭, 및 개행문자로 설정되어 있다

   -> IFS는 단어(token)의 구분에 사용된다


2. 함수

 - 함수는 명령이나 명령 집합에 대한 이름으로 효율성을 높이거나, 프로그램의 모듈화를 위해 사용한다

 - 함수는 현재 쉘 내에서 실행되며 자식 프로세스를 생성하지 않고 함수를 실행 시킨다

 - 함수는 다른 파일에 저장하여 두었다가 필요할 때 스크립트에서 호출하여 사용할 수 있다

  1. 쉘에서는 사용자의 입력이 내장 명령인지, 함수인지, 아니면 디스크에서 찾아야하는 실행 
     프로그램(혹은 스크립트)인지 판단하는 과정을 거쳐 별명인지를 우선 판단하고, 다음으로 
     함수인지 검사한 다음, 내장 명령인지 확인한다. 마지막으로 실행 프로그램인지 확인한다

  2. 함수는 사용하기 전에 정의해야 한다

  3. 함수는 현재 환경 하에서 실행되며 호출한 스크립트와 변수를 공유할 뿐만 아니라, 매개변수 역시 
     위치 매개변수로 지정하여 함수에 전달할 수 있다. local 함수를 사용하여 지역변수를 함수 내에서 
     생성하여 사용할 수 있다

  4. 만약 함수 안에서 exit 명령을 실행하면 스크립트 자체가 종료된다. 함수가 종료한 후, 복귀 지점은 
     스크립트에서 함수를 호출한 곳이 된다

  5. 함수 내에서 사용한 return 문은 가장 최근에 실행된 명령의 종료 상태값이나, 지정한 매개 변수값을 
     반환한다

  6. 내장 명령 export -f 를 사용하면 함수를 자식 쉘에 익스포트 할 수 있다

  7. declare -f 명령을 사용해서 함수와 그 정의를 출력할 수 있다 
     declare -F 명령을 사용하면 함수의 이름만 출력한다

  8. 트랩(trap)은 변수처럼 함수 간에도 전역이며 함수에서 정의한 경우에도 호출한 스크립트와 공유한다

  9. 함수가 다른 파일에 저장되어 있다면 마침표(. 혹은 source) 명령을 사용하여 현재 스크립트에
     들일 수 있다

  10. 함수는 자신을 호출할 수 있으며 재귀 호출의 횟수에는 제한이 없다

 - 형식

  function 함수이름 { 명령(들) ; 명령(들); }


 - 함수 설정 해제

  -> unset 명령을 사용하면 함수를 메모리에서 제거할 수 있다

  -> 형식

   unset -f function_name


 - 함수의 익스포트(export)

  -> 함수를 자식 쉘들에게 익스포트할 수 있다

  -> 형식

   export -f function_name


 - 함수 매개변수와 반환값

  -> 매개변수

   => 매개변수의 전달은 위치 매개변수를 사용하여 함수로 넘겨줄 수 있다

   => 함수에서 사용하는 위치 매개변수는 통용범위(scope)가 함수 내로 한정된다

   => 함수의 매개변수는 함수 밖에서 사용 중인 다른 위치 매개변수에게는 아무런 영향을 미치지 않는다


  -> 내장 명령 local

   => 내장 명령 local을 사용하면 현재 함수에게만 유효한 지역 변수를 생성시킬 수 있다


  -> return 내장 명령

   => return 명령은 함수를 종료한 후, 제어를 함수를 호출한 곳으로 되돌려준다

   => return 명령에 아무런 매개변수도 지정하지 않은 경우, 함수의 반환값은 스크립트 안에서
       최근에 사용된 명령의 종료 상태가 된다

   => 유닉스 명령의 출력을 가져올 때와 동일하게 함수 전체를 괄호 안에 넣고 괄호 앞에 달러기호($)를
       사용하면 출력을 특정 변수에 저장할 수 있다


 - 함수와 source(dot) 명령

  -> 저장함수

   => 함수를 종종 .profile에 정의하여 사용자가 로그인함과 동시에 정의되도록 한다

   => 함수는 익스포트(export)할 수 있을 뿐만 아니라, 다른 파일에 저장할 수도 있다.

   => 저장해둔 함수가 필요한 경우에는 마침표(. 혹은 source) 명령과 파일명을 입력하면,
       함수의 정의가 활성화 된다

   
   $ cat test

   function go () { 
    cd $HOME/bin/prog
    PS1=''pwd' > '
    ls
   }

   function greetings () { echo "Hi $1! Welcome to my world." ; }

   
   $ source test

    > 마침표(. 혹은 source) 명령으로 test  파일의 내용을 쉘 메모리로 
      불러와 두 함수가 현재 쉘에서 정의된다

   $ greetings aaa
   Hi aaa! Welcome to my world.

출처 :  http://blog.blueweb.co.kr/194?category=18

LIST

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

[펌]Apache 403 Forbidden error 해결 방법  (4) 2011.12.08
AWK 명령어  (0) 2011.04.24
VI편집기(VIM)  (1) 2011.04.22
bash 쉘 스크립트  (0) 2011.04.22
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.