case와 select는 코드 블럭을 반복해서 수행하지 않기 때문에 기술적으로 루프가 아닙니다. 하지만 루프가 하는 것처럼 특정 블럭의 위나 아래에서 주어진 조건에 따라 프로그램 흐름을 조정해 줍니다.
case는 C/C++의 switch와 동일합니다. 조건에 따라 여러개의 코드 블럭중 하나로 분기할 수 있게 해주는데, 여러개의 if/then/else의 간단한 표기법처럼 동작하기 때문에 메뉴같은 것을 만들 때 적당합니다.
case "$variable" in
"$condition1" )
command...
;;
"$condition2" )
command...
;;
esac
참고:
낱말 조각남(word splitting)이 일어나지 않기 때문에 꼭 variable을 쿼우팅 하지 않아도 됩니다.
각 조건들은 오른쪽 괄호, )로 끝납니다.
각 조건 블럭은 이중 세미콜론, ;;.
전체 case 블럭은 esac로 끝납니다(case를 거꾸로 스펠링).
예 10-22. case 쓰기
#!/bin/bash echo; echo "아무키나 누른 다음 리턴을 치세요." read Keypress case "$Keypress" in [a-z] ) echo "소문자";; [A-Z] ) echo "대문자";; [0-9] ) echo "숫자";; * ) echo "구두점이나, 공백문자 등등";; esac # [대괄호]속 범위의 문자들을 받아 들입니다. # 독자들용 연습문제: # 이 스크립트는 한개의 키누름만 받아들이고 종료합니다. # 이를 키가 눌릴때마다 무슨 키인지 계속 보여주면서 # 키가 "X"일 경우에만 종료하도록 고쳐보세요. # 힌트: "while"루프로 다 감싸면? exit 0 |
예 10-23. case로 메뉴 만들기
#!/bin/bash # 조잡한 주소 데이타베이스 clear # 화면을 정리하고 echo " 주소록" echo " ------" echo "다음중 한 명을 고르세요:" echo echo "[E]vans, Roland" echo "[J]ones, Mildred" echo "[S]mith, Julie" echo "[Z]ane, Morris" echo read person case "$person" in # 변수가 쿼우트 된 것에 주의하세요. "E" | "e" ) # 대소문자 모두 인식. echo echo "Roland Evans" echo "4321 Floppy Dr." echo "Hardscrabble, CO 80753" echo "(303) 734-9874" echo "(303) 734-9892 fax" echo "revans@zzy.net" echo "Business partner & old friend" ;; # 이중 세미콜론이 각 옵션을 끝내게 해 주는 것을 눈여겨 봐두세요. "J" | "j" ) echo echo "Mildred Jones" echo "249 E. 7th St., Apt. 19" echo "New York, NY 10009" echo "(212) 533-2814" echo "(212) 533-9972 fax" echo "milliej@loisaida.com" echo "Girlfriend" echo "Birthday: Feb. 11" ;; # Smith & Zane 은 나중에 추가. * ) # 디폴트 옵션. # 그냥 리턴을 쳐도 여기로 옵니다. echo echo "아직 등록이 안 돼 있습니다." ;; esac echo # 독자용 연습문제: # 입력을 한 번만 받고 끝내지 말고 계속 받을 수 있게 고쳐보세요. exit 0 |
명령어줄 매개변수를 확인하려고 할 때, 아주 창의적인 방법으로 case를 사용하는 법을 보여 드리겠습니다.
#! /bin/bash case "$1" in "") echo "사용법: ${0##*/} <filename>"; exit 65;; # 명령어 줄 매개변수를 안 적었거나 # 첫번째 매개변수가 비어 있을 때 # ${0##*/} 는 매개변수 치환인 ${var##pattern} 이기 때문에 결과는 $0 이 됩니다. -*) FILENAME=./$1;; # 첫번째 인자($1)인 filename이 대쉬(-)로 시작한다면 # ./$1 로 바꿉니다. # 따라서, 다른 명령어들은 이것을 옵션으로 해석하지 못하게 됩니다. * ) FILENAME=$1;; # 아무 것도 아니면, $1. esac |
예 10-24. case용 변수를 만들기 위해서 명령어 치환 쓰기
#!/bin/bash # "case"용 변수를 만들기 위해서 명령어 치환 쓰기.. case $( arch ) in # "arch" 는 머신 아키텍쳐를 리턴합니다. i386 ) echo "80386 기반의 머신";; i486 ) echo "80486 기반의 머신";; i586 ) echo "Pentium 기반의 머신";; i686 ) echo "Pentium2+ 기반의 머신";; * ) echo "다른 형태의 머신";; esac exit 0 |
case는 globbing용 패턴으로 문자열을 필터링 할 수 있습니다.
예 10-25. 간단한 문자열 매칭
#!/bin/bash # match-string.sh: 간단한 문자열 매칭 match_string () { MATCH=0 NOMATCH=90 PARAMS=2 # 이 함수는 2개의 인자가 필요합니다. BAD_PARAMS=91 [ $# -eq $PARAMS ] || return $BAD_PARAMS case "$1" in "$2") return $MATCH;; * ) return $NOMATCH;; esac } a=one b=two c=three d=two match_string $a # 잘못된 인자 갯수 echo $? # 91 match_string $a $b # 일치하지 않음 echo $? # 90 match_string $b $d # 일치함 echo $? # 0 exit 0 |
예 10-26. 입력이 알파벳인지 확인하기
#!/bin/bash # 문자열을 필터링하기 위해서 "case" 구문 쓰기. SUCCESS=0 FAILURE=-1 isalpha () # 입력 문자열의 "첫번째 문자"가 알파벳인지 아닌지 확인. { if [ -z "$1" ] # 인자 없이 넘어왔군. then return $FAILURE fi case "$1" in [a-zA-Z]*) return $SUCCESS;; # 문자로 시작하는지. * ) return $FAILURE;; esac } # C 의 "isalpha()" 함수와 비교해 보세요. isalpha2 () # "문자열 전체"가 알파벳인지 확인. { [ $# -eq 1 ] || return $FAILURE case $1 in *[!a-zA-Z]*|"") return $FAILURE;; *) return $SUCCESS;; esac } check_var () # isalpha() 의 프론트엔드(front-end) { if isalpha "$@" then echo "$* = 알파벳" else echo "$* = 알파벳 아님" # 인자가 없어도 "알파벳 아님"임. fi } a=23skidoo b=H3llo c=-What? d=`echo $b` # 명령어 치환. check_var $a check_var $b check_var $c check_var $d check_var # 인자없이 부르면 어떻게 될까요? # S.C. 가 더 좋게 고침. exit 0 |
select는 Korn 쉘에서 따온 것인데 메뉴를 만들때 쓸 수 있습니다.
select variable [in list]
do
command...
break
done
사용자가 list에 있는 것중 하나를 고를 수 있게 해 줍니다. 기본적으로 PS3(#? ) 프롬프트를 쓰고 이 값은 바꿀 수 있다는 것에 주의하기 바랍니다.
예 10-27. select로 메뉴 만들기
#!/bin/bash PS3='제일 좋아하는 야채를 고르세요: ' # 프롬프트 문자열 세트. echo select vegetable in "콩" "당근" "감자" "양파" "순무" do echo echo "제일 좋아하는 야채가 $vegetable 이네요." echo "깔깔~~" echo break # 여기에 'break'가 없으면 무한 루프를 돕니다. done exit 0 |
in list를 안 쓰면 select는 스크립트나 select를 포함하고 있는 함수로 넘어온 명령어 줄 인자($@)을 사용합니다.
in list가 빠졌을 경우를
for variable [in list]
의 경우와 비교해 보세요.예 10-28. 함수에서 select를 써서 메뉴 만들기
#!/bin/bash PS3='제일 좋아하는 야채를 고르세요: ' echo choice_of() { select vegetable # select 에 [in list] 가 빠져있기 때문에, 함수로 넘어온 인자를 씁니다. do echo echo "제일 좋아하는 야채가 $vegetable 군요." echo "껄껄~~" echo break done } choice_of 콩 쌀 당근 무 토마토 시금치 # $1 $2 $3 $4 $5 $6 # choice_of() 함수로 넘어갑니다. exit 0 |